2012-04-09 2 views
1

Я использую руководство по созданию отношений n-to-n в Orchard (ocs.orchardproject.net/Documentation/Creating-1-n-and-nn-relations) с некоторые незначительные изменения. Хотя пример кода хорошо работает, моя собственная часть контента всегда пуста после создания или редактирования элемента. Я не могу понять, потому что я ругаюсь мой код почти идентичен их (за исключением частей контента, имеющих больше/меньше несвязанных полей).Пустой элемент содержимого после создания/редактирования в Orchard

Я подозреваю, что это может иметь отношение к префиксу в драйвере. Я действительно не знаю, что должен делать префикс, но при установке его на одно значение возникает ошибка времени выполнения при создании/редактировании, другие значения просто приводят к результату при всех пустых полях.

Оригинальный образец работает отлично, поэтому это должно быть то, что я делал или не делал, но я просто не могу понять, что это.

Некоторые соответствующие классы:

using System.Linq; 
using JetBrains.Annotations; 
using Orchard.ContentManagement; 
using Orchard.ContentManagement.Drivers; 
using ArealAds.Models; 
using ArealAds.Services; 
using ArealAds.ViewModels; 

namespace ArealAds.Drivers { 
    [UsedImplicitly] 
    public class StreetPartDriver : ContentPartDriver<StreetPart> { 
     private readonly IStreetService _streetService; 

     private const string TemplateName = "Parts/Street"; 

     public StreetPartDriver(IStreetService streetService) { 
      _streetService = streetService; 
     } 

     // this one gives a runtime error with blank description, 
     // other values produce result with all fields blank 
     protected override string Prefix { 
      get { return "Area"; } 
     } 

     protected override DriverResult Display(StreetPart part, string displayType, dynamic shapeHelper) { 
      return ContentShape("Parts_Street", 
          () => shapeHelper.Parts_Street(
           ContentPart: part, 
           Name: part.Name, 
           Areas: part.Areas, 
           Districts: part.Districts)); 

     } 

     protected override DriverResult Editor(StreetPart part, dynamic shapeHelper) { 
      return ContentShape("Parts_Street_Edit", 
        () => shapeHelper.EditorTemplate(
         TemplateName: TemplateName, 
         Model: BuildEditorViewModel(part), 
         Prefix: Prefix)); 
     } 

     protected override DriverResult Editor(StreetPart part, IUpdateModel updater, dynamic shapeHelper) { 
      var model = new EditStreetViewModel(); 
      updater.TryUpdateModel(model, Prefix, null, null); 

      if (part.ContentItem.Id != 0) { 
       _streetService.UpdateAreasForContentItem(part.ContentItem, model.Areas); 
      } 

      return Editor(part, shapeHelper); 
     } 

     private EditStreetViewModel BuildEditorViewModel(StreetPart part) { 
      var itemAreas = part.Areas.ToLookup(r => r.Id); 
      return new EditStreetViewModel { 
       Areas = _streetService.GetAreas().Select(r => new AreaEntry { 
        Area = r, 
        IsChecked = itemAreas.Contains(r.Id) 
       }).ToList() 
      }; 
     } 
    } 
} 


using System.Collections.Generic; 
using System.Linq; 
using Orchard; 
using Orchard.ContentManagement; 
using Orchard.Data; 
using ArealAds.Models; 
using ArealAds.ViewModels; 

namespace ArealAds.Services { 
    public interface IStreetService : IDependency { 
     void UpdateAreasForContentItem(ContentItem item, IEnumerable<AreaEntry> areas); 
     IEnumerable<AreaRecord> GetAreas(); 
    } 

    public class StreetService : IStreetService { 
     private readonly IRepository<AreaRecord> _areaRepository; 
     private readonly IRepository<StreetAreaRecord> _streetAreaRepository; 

     public StreetService(
      IRepository<AreaRecord> areaRepository, 
      IRepository<StreetAreaRecord> streetAreaRepository) { 

      _areaRepository = areaRepository; 
      _streetAreaRepository = streetAreaRepository; 
     } 

     public void UpdateAreasForContentItem(ContentItem item, IEnumerable<AreaEntry> areas) { 
      var record = item.As<StreetPart>().Record; 
      var oldAreas = _streetAreaRepository.Fetch(
       r => r.StreetRecord == record); 
      var lookupNew = areas 
       .Where(e => e.IsChecked) 
       .Select(e => e.Area) 
       .ToDictionary(r => r, r => false); 
      // Delete the areas that are no longer there and mark the ones that should stay 
      foreach(var streetAreaRecord in oldAreas) { 
       if (lookupNew.ContainsKey(streetAreaRecord.AreaRecord)) { 
        lookupNew[streetAreaRecord.AreaRecord] = true; 
       } 
       else { 
        _streetAreaRepository.Delete(streetAreaRecord); 
       } 
      } 
      // Add the new areas 
      foreach(var area in lookupNew.Where(kvp => !kvp.Value).Select(kvp => kvp.Key)) { 
       _streetAreaRepository.Create(new StreetAreaRecord { 
        StreetRecord = record, 
        AreaRecord = area 
       }); 
      } 
     } 

     public IEnumerable<AreaRecord> GetAreas() { 
      return _areaRepository.Table.ToList(); 
     } 
    } 
} 


using System.ComponentModel.DataAnnotations; 
using Orchard.ContentManagement; 
using Orchard.ContentManagement.Records; 

namespace ArealAds.Models { 
    public class StreetAreaRecord : ContentPartRecord { 
     public virtual StreetRecord StreetRecord { get; set; } 
     public virtual AreaRecord AreaRecord { get; set; } 
    } 
} 

using System; 
using System.Collections.Generic; 
using System.Data; 
using Orchard.ContentManagement.Drivers; 
using Orchard.ContentManagement.MetaData; 
using Orchard.ContentManagement.MetaData.Builders; 
using Orchard.Core.Contents.Extensions; 
using Orchard.Data.Migration; 
using ArealAds.Models; 

namespace ArealAds { 
    public class Migrations : DataMigrationImpl { 

     public int Create() { 
      // 
      // Street-Area-District 
      // 

      SchemaBuilder.CreateTable("DistrictRecord", table => table 
       .ContentPartRecord() 
       .Column<string>("Name") 
      ); 

      ContentDefinitionManager.AlterPartDefinition(
       typeof(DistrictPart).Name, cfg => cfg.Attachable()); 

      ContentDefinitionManager.AlterTypeDefinition(
       "District", cfg => cfg 
       .WithPart("CommonPart") 
       .WithPart("DistrictPart") 
       .Creatable() 
      ); 

      SchemaBuilder.CreateTable("AreaRecord", table => table 
       .ContentPartRecord() 
       .Column<string>("Name") 
       .Column<int>("DistrictRecord_Id") 
      ); 

      ContentDefinitionManager.AlterPartDefinition(
       typeof(AreaPart).Name, cfg => cfg.Attachable()); 

      ContentDefinitionManager.AlterTypeDefinition(
       "Area", cfg => cfg 
       .WithPart("CommonPart") 
       .WithPart("AreaPart") 
       .Creatable() 
      ); 

      SchemaBuilder.CreateTable("StreetRecord", table => table 
       .ContentPartRecord() 
       .Column<string>("Name") 
      ); 

      ContentDefinitionManager.AlterPartDefinition(
       typeof(StreetPart).Name, cfg => cfg.Attachable()); 

      ContentDefinitionManager.AlterTypeDefinition(
       "Street", cfg => cfg 
       .WithPart("CommonPart") 
       .WithPart("StreetPart") 
       .Creatable() 
      ); 

      SchemaBuilder.CreateTable("StreetAreaRecord", table => table 
       .Column<int>("Id", column => column.PrimaryKey().Identity()) 
       .Column<int>("StreetRecord_Id") 
       .Column<int>("AreaRecord_Id") 
      ); 


      // 
      // Address-Ad 
      // 

      SchemaBuilder.CreateTable("AddressRecord", table => table 
       .ContentPartRecord() 
       .Column<int>("StreetRecord_Id") 
       .Column<int>("Building") 
       .Column<int>("Kor") 
       .Column<int>("Str") 
       .Column<int>("Vl") 
       .Column<string>("Note") 
       .Column<int>("AreaRecord_Id") 
       .Column<int>("DistrictRecord_Id") 
       .Column<string>("Phone1") 
       .Column<string>("Phone2") 
       .Column<string>("Phone3") 
      ); 

      ContentDefinitionManager.AlterPartDefinition(
       typeof(AddressPart).Name, cfg => cfg.Attachable()); 


      return 1; 
     } 
    } 
} 

@model ArealAds.ViewModels.EditStreetViewModel 
<fieldset> 
    <legend>Улица</legend> 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.Street.Name) 
    </div> 
    <div class="editor-field"> 
     @Html.TextBoxFor(model => model.Street.Name) 
     @Html.ValidationMessageFor(model => model.Street.Name) 
    </div> 
<ul> 

@for (int i = 0; i < Model.Areas.Count; i++) { 
    <li> 
     <input type="hidden" value="@Model.Areas[i].Area.Id" 
       name="@Html.FieldNameFor(m => m.Areas[i].Area.Id)"/> 

     <label for="@Html.FieldNameFor(m => m.Areas[i].IsChecked)"> 

      <input type="checkbox" value="true" 
       name="@Html.FieldNameFor(m => m.Areas[i].IsChecked)" 
       id="@Html.FieldNameFor(m => m.Areas[i].IsChecked)" 
       @if (Model.Areas[i].IsChecked) {<text>checked="checked"</text>}/> 

      @Model.Areas[i].Area.Name 
     </label> 
    </li> 
} 
</ul> 
</fieldset> 

я бил головой о стену на этом в течение нескольких дней, пожалуйста, какие-либо предложения, которые вы чувствуете, может теоретически помочь «потому что я в отчаянии :(

UPD: StreetHandler класс:

using ArealAds.Models; 
using Orchard.ContentManagement.Handlers; 
using Orchard.Data; 

namespace ArealAds.Handlers { 
    public class StreetHandler : ContentHandler { 
     public StreetHandler(IRepository<StreetRecord> repository) { 
      Filters.Add(StorageFilter.For(repository)); 
     } 
    } 
} 

Существует исключение на бревне:

2012-04-10 00:07:58,515 [7] Orchard.ContentManagement.Drivers.Coordinators.ContentPartDriverCoordinator - IdentifierGenerationException thrown from IContentPartDriver by ArealAds.Drivers.StreetPartDriver 
NHibernate.Id.IdentifierGenerationException: attempted to assign id from null one-to-one property: ContentItemRecord 
    â NHibernate.Id.ForeignGenerator.Generate(ISessionImplementor sessionImplementor, Object obj) 
    â NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess) 
    â NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) 
    â NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event) 
    â NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event) 
    â NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event) 
    â NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event) 
    â NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event) 
    â NHibernate.Impl.SessionImpl.Save(Object obj) 
    â Orchard.Data.Repository`1.Create(T entity) â d:\TeamCity\Projects\Orchard-Default\src\Orchard\Data\Repository.cs:ñòðîêà 96 
    â Orchard.Data.Repository`1.Orchard.Data.IRepository<T>.Create(T entity) â d:\TeamCity\Projects\Orchard-Default\src\Orchard\Data\Repository.cs:ñòðîêà 36 
    â ArealAds.Services.StreetService.UpdateAreasForContentItem(ContentItem item, IEnumerable`1 areas) â c:\Users\Mom\Teritoriya\Modules\ArealAds\Services\Street.cs:ñòðîêà 46 
    â ArealAds.Drivers.StreetPartDriver.Editor(StreetPart part, IUpdateModel updater, Object shapeHelper) â c:\Users\Mom\Teritoriya\Modules\ArealAds\Controllers\Street.cs:ñòðîêà 47 
    â System.Dynamic.UpdateDelegates.UpdateAndExecute4[T0,T1,T2,T3,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3) 
    â Orchard.ContentManagement.Drivers.ContentPartDriver`1.Orchard.ContentManagement.Drivers.IContentPartDriver.UpdateEditor(UpdateEditorContext context) â d:\TeamCity\Projects\Orchard-Default\src\Orchard\ContentManagement\Drivers\ContentPartDriver.cs:ñòðîêà 30 
    â Orchard.ContentManagement.Drivers.Coordinators.ContentPartDriverCoordinator.<>c__DisplayClass10.<UpdateEditor>b__f(IContentPartDriver driver) â d:\TeamCity\Projects\Orchard-Default\src\Orchard\ContentManagement\Drivers\Coordinators\ContentPartDriverCoordinator.cs:ñòðîêà 61 
    â Orchard.InvokeExtensions.Invoke[TEvents](IEnumerable`1 events, Action`1 dispatch, ILogger logger) â d:\TeamCity\Projects\Orchard-Default\src\Orchard\InvokeExtensions.cs:ñòðîêà 19 

EDIT: некоторые классы моделей:

using System.ComponentModel.DataAnnotations; 
using Orchard.ContentManagement; 
using Orchard.ContentManagement.Records; 

namespace ArealAds.Models { 
    public class AreaRecord : ContentPartRecord { 
     public virtual string Name { get; set; } 
     public virtual DistrictRecord DistrictRecord { get; set; } 
    } 

    public class AreaPart : ContentPart<AreaRecord> { 
     [Required] 
     public string Name { 
      get { return Record.Name; } 
      set { Record.Name = value; } 
     } 

     [Required] 
     public DistrictRecord DistrictRecord { 
      get { return Record.DistrictRecord; } 
      set { Record.DistrictRecord = value; } 
     } 
    } 
} 

using System.Collections.Generic; 
using System.Linq; 
using System.ComponentModel.DataAnnotations; 
using Orchard.ContentManagement; 
using Orchard.ContentManagement.Records; 

namespace ArealAds.Models { 
    public class StreetRecord : ContentPartRecord { 
     public virtual string Name { get; set; } 
     public virtual IList<StreetAreaRecord> Areas { get; set; } 

     public StreetRecord() { 
      Areas = new List<StreetAreaRecord>(); 
     } 
    } 

    public class StreetPart : ContentPart<StreetRecord> { 
     [Required] 
     public string Name { 
      get { return Record.Name; } 
      set { Record.Name = value; } 
     } 

     public IEnumerable<AreaRecord> Areas { 
      get { 
       return Record.Areas.Select (r => r.AreaRecord); 
      } 
     } 

     public IEnumerable<DistrictRecord> Districts { 
      get { 
       return Record.Areas.Select (r => r.AreaRecord.DistrictRecord).Distinct(); 
      } 
     } 
    } 
} 

using System.ComponentModel.DataAnnotations; 
using Orchard.ContentManagement; 
using Orchard.ContentManagement.Records; 

namespace ArealAds.Models { 
    public class StreetAreaRecord : ContentPartRecord { 
     public virtual StreetRecord StreetRecord { get; set; } 
     public virtual AreaRecord AreaRecord { get; set; } 
    } 
} 

using ArealAds.Models; 
using Orchard.ContentManagement.Handlers; 
using Orchard.Data; 

namespace ArealAds.Handlers { 
    public class AreaHandler : ContentHandler { 
     public AreaHandler(IRepository<AreaRecord> repository) { 
      Filters.Add(StorageFilter.For(repository)); 
     } 
    } 
} 

using ArealAds.Models; 
using Orchard.ContentManagement.Handlers; 
using Orchard.Data; 

namespace ArealAds.Handlers { 
    public class StreetHandler : ContentHandler { 
     public StreetHandler(IRepository<StreetRecord> repository) { 
      Filters.Add(StorageFilter.For(repository)); 
     } 
    } 
} 

ответ

2

В вашей модели StreetAreaRecord отсутствует свойство Id. Поскольку это не ContentPartRecord, вам необходимо настроить свойство вручную.

public virtual int Id { get; set; } 
+0

Это фиксировало некоторые поля, но поле Street.Name по-прежнему не установлено должным образом :( –

+0

Рад это слышать. Можете ли вы опубликовать журналы ошибок с момента создания/сохранения и Street.Name не сохранить? Вероятно, это теперь вы можете исправить эту проблему. Это просто улица.Поле имени, которое не сохраняется, или весь StreetRecord не создается? –

+0

Я исправил проблему с помощью Street.Name, она была совершенно не связана. Спасибо, что потратили свое время, помогая мне, я надеюсь, что это «тематическое исследование» поможет другим людям :) –

0

Префикс обеспечить уникальный идентификатор атрибута в HTML-полей в редакторе части. У вас может быть несколько частей в одном типе содержимого с полем «Имя». Без префикса html недействителен, и postback не будет работать, потому что будет два поля с id = "Name". Вы можете просто установить префикс как имя части.

Я не уверен, что префикс - это то, что мешает вашей части сохранить. Вы проверили Handler для своей части? Удостоверьтесь, что он устанавливает фильтр для StreetPartRecord, что часто является причиной новой части, не сохраняющей при обратной передаче.

+0

Благодарим за ответ. Я добавил содержимое файла класса обработчика в свой вопрос. Он выглядит полностью аналогичным тому, который показан в образце. Я также добавил префиксы в каждом драйвере. Еще ничего хорошего. –

+0

Любые ошибки в журналах (Orchard.Web \ App_Data \ Logs \)? –

+0

Действительно! Как я мог забыть о бревнах? <_ <Теперь мне может понадобиться помощь в расшифровке ... Я отредактировал вопрос соответствующим образом. –

Смежные вопросы