Reputation: 30
My Orchard code generated module and part will not call the editor method in it's driver class and so does not load the editor template view showing the part properties. It also does not write to the custom database table the module created, but it does allow for saving and creates the associated content item.
The module as project builds in visual studio, and I can get debug to hit the constructor method of the Driver, but it will not hit Editor() or Display() or the Editor() postback.
I built an Orchard module using the codegen and code generation extensions module. codegen part is from the Code Generations Extensions module, the rest is from the core Code Generation module. I created the module, added a content part with properties and generated a datamigration.
Here are the commands I used:
codegen module "TestModule.Foo"
codegen part "TestModule.Foo" Bar /Properties:Description:string,Broken:bool
codegen datamigration "TestModule.Foo"
The only code change I made was to make the type creatable() via a migration update. I confirmed that this ran and I can see the content type option to create a new Bar Record in the admin. I also hand edited the placement.info file to add the placement tag for the Parts_Bar_Edit shape.
Here's all the code that is being used:
Migration.cs:
using System.Data; using Orchard.ContentManagement.MetaData; using Orchard.Core.Contents.Extensions; using Orchard.Data.Migration; namespace TestModule.Foo { public class Migrations : DataMigrationImpl { public int Create() { // Creating table BarRecord SchemaBuilder.CreateTable("BarRecord", table => table .ContentPartRecord() .Column("Description", DbType.String) .Column("Broken", DbType.Boolean) ); return 1; } public int UpdateFrom1() { ContentDefinitionManager.AlterTypeDefinition("BarRecord", cfg => cfg .Creatable() ); return 2; } } }
Placement.info:
<Placement> <Place Parts_Bar="Content:5"/> <Place Parts_Bar_Edit="Content:7.5" /> </Placement>
Models/Bar.cs:
using Orchard; using Orchard.ContentManagement; namespace TestModule.Foo.Models { public class Bar : ContentPart { public string Description { get { return Record.Description; } set { Record.Description = value; } } public bool Broken { get { return Record.Broken; } set { Record.Broken = value; } } } }
Models/BarRecord.cs
using Orchard; using Orchard.ContentManagement.Records; namespace TestModule.Foo.Models { public class BarRecord : ContentPartRecord { public virtual string Description{ get; set; } public virtual bool Broken{ get; set; } } }
Handlers/BarHandler.cs
using JetBrains.Annotations; using Orchard.ContentManagement.Handlers; using Orchard.Data; using TestModule.Foo.Models; namespace TestModule.Foo.Handlers { [UsedImplicitly] public class BarHandler : ContentHandler { public BarHandler(IRepository repository) { Filters.Add(StorageFilter.For(repository)); } } }
Drivers/BarDrivers.cs
using JetBrains.Annotations; using Orchard.ContentManagement; using Orchard.ContentManagement.Drivers; using Orchard.Localization; using Orchard.UI.Notify; using TestModule.Foo.Models; namespace TestModule.Foo.Drivers { [UsedImplicitly] public class BarDriver : ContentPartDriver { private readonly INotifier _notifier; private const string TemplateName = "Parts/Bar"; public Localizer T { get; set; } public BarDriver(INotifier notifier) { _notifier = notifier; T = NullLocalizer.Instance; } protected override DriverResult Display(Bar part, string displayType, dynamic shapeHelper) { return ContentShape("Parts_Bar", () => shapeHelper.Parts_Bar(ContentItem: part.ContentItem)); } protected override DriverResult Editor(Bar part, dynamic shapeHelper) { return ContentShape("Parts_Bar", () => shapeHelper.EditorTemplate(TemplateName: TemplateName, Model:part, Prefix: Prefix));` } protected override DriverResult Editor(Bar part, IUpdateModel updater, dynamic shapeHelper) { if (updater.TryUpdateModel(part, Prefix, null, null)) { _notifier.Information(T("Bar edited successfully")); } else { _notifier.Error(T("Error during Bar update!")); } return Editor(part, shapeHelper); } } }
Views/EditorTemplates/Parts/Bar.cshtml
@model TestModule.Foo.Models.Bar @using Orchard.ContentManagement; @{ Layout.Title = T("Edit Bar").ToString(); } <fieldset> <legend>@T("Bar settings")</legend> <div> @Html.LabelFor(m => m.Description, @T("Description")) @Html.EditorFor(m => m.Description) @Html.ValidationMessageFor(m => m.Description, "*") </div> <div> @Html.LabelFor(m => m.Broken, @T("Broken")) @Html.EditorFor(m => m.Broken) @Html.ValidationMessageFor(m => m.Broken, "*") </div> </fieldset>
Views/Parts/Bar.cshtml
@model dynamic
I'm using Orchard 1.6.1 and have been able to replicate the same behavior on the 1.7rc. I'm completely stumped and frustrated at this point, so any help would be greatly appreciated. Thanks.
Upvotes: 0
Views: 886
Reputation: 6581
A few things...
Bar.cs
public class Bar : ContentPart<BarRecord> {
BarHandler.cs
public BarHandler(IRepository<BarRecord> repository)
And in your migrations part, I think what you probably want to be doing is altering the part. So it would be more like this:
public int UpdateFrom1() {
ContentDefinitionManager.AlterPartDefinition("Bar", cfg => cfg
.Attachable()
);
return 2;
}
What you are doing is creating a type called BarRecord and making it creatable, not actually attaching the part to it. Or letting that part be attached. So if you want a Bar type, it would be as you did before as well:
public int UpdateFrom1() {
ContentDefinitionManager.AlterPartDefinition("Bar", cfg => cfg
.Attachable()
);
ContentDefinitionManager.AlterTypeDefinition("BarType", cfg => cfg
.Creatable()
.WithPart("Bar")
);
return 2;
}
The stuff in the models and the handler should have been done for you by the code generation. So that is a bit strange. Maybe you need to adhere to naming conventions and add Part to the end. So "BarPart" instead of "Bar". Or that you have " " around your module name. I'm not sure. Contact the author of the module if you cant get it to work. He is a top guy
Upvotes: 0