Custom content part wrapped by system ContentPart?

Topics: Core, Customizing Orchard
Apr 17, 2013 at 1:22 PM
Edited Apr 17, 2013 at 4:50 PM
Please can anybody shed light on my problem.
I have got 2 created through migration content types: Organisation and Application. They are similarly defined. I want to create them and set some properties via content part.
            var contentItem = _contentManager.New("Organisation");
            var organisationPart = contentItem.As<OrganisationPart>();
            ....                      
            var contentItem = _contentManager.New("Application");
            var applicationPart = contentItem.As<ApplicationPart>();
It is all fine with the first one: Parts collection contains OrganisationPart so organisationPart variable can be used for properties assignments.
But applicationPart is always null. It is because second contentItem's Parts collection contains not ApplicationPart but ContentManagement.ContentPart wrapping ApplicationPart.
I can't find why that wrapping occurs. May be it is simple and somebody has it on top of his head?
Apr 17, 2013 at 3:56 PM
could you please show us your migrations?
Apr 17, 2013 at 4:36 PM
Sure but they are very similar
            SchemaBuilder.CreateTable("OrganisationRecord", table => table
                .ContentPartRecord()
                .Column<string>("OrganisationName", column => column.WithLength(50))
                .Column<string>("PostCode", column => column.WithLength(15))
                .Column<string>("AddressLine", column => column.WithLength(500))
                );

            ContentDefinitionManager.AlterPartDefinition(typeof(OrganisationPart).Name, part => part
                .Attachable()
                );

            ContentDefinitionManager.AlterTypeDefinition("Organisation", t => t
               .WithPart("CommonPart")
               .WithPart("SocketsPart")
               .WithPart(typeof(OrganisationPart).Name)
               );
and
           SchemaBuilder.CreateTable("ApplicationRecord",
                table => table
                    .ContentPartRecord()
                    .Column<int>("OrgIdentifier")
                    .Column<int>("RoundId")
                    .Column<string>("Name", column => column.WithLength(4096))
                );
            
            ContentDefinitionManager.AlterPartDefinition(typeof(ApplicationPart).Name, part => part
                .Attachable()
                );

            ContentDefinitionManager.AlterTypeDefinition("Application", t => t
               .WithPart("CommonPart")
               .WithPart("SocketsPart")
               .WithPart(typeof(ApplicationPart).Name)
               );
Apr 17, 2013 at 4:39 PM
And their definition
    public class OrganisationPart : ContentPart<OrganisationRecord>, ITitleAspect
    {
        public string OrganisationName
        {
            get { return Record.OrganisationName; }
            set { Record.OrganisationName = value; }
        }
        public string PostCode
        {
            get { return Record.PostCode; }
            set { Record.PostCode = value; }
        }
        public string AddressLine
        {
            get { return Record.AddressLine; }
            set { Record.AddressLine = value; }
        }

        public string Title
        {
            get { return Record.OrganisationName; }
        }
        
    }

    public class OrganisationRecord : ContentPartRecord
    {
        public virtual string OrganisationName { get; set; }
        public virtual string PostCode { get; set; }
        public virtual string AddressLine { get; set; }
    }
and
public class ApplicationPart : ContentPart<ApplicationRecord>, ITitleAspect
    {
        public string Title {
            get { return String.IsNullOrEmpty(Record.Name) ? "Untitled" : Record.Name; }
        }

        public string Name
        {
            get { return Record.Name; }
            set { Record.Name = value; }
        }
        public int OrgIdentifier
        {
            get { return Record.OrgIdentifier; }
            set { Record.OrgIdentifier = value; }
        }
        public int RoundId
        {
            get { return Record.RoundId; }
            set { Record.RoundId = value; }
        }
    }

    public class ApplicationRecord : ContentPartRecord
    {
        public virtual string Name { get; set; }
        public virtual int OrgIdentifier { get; set; }
        public virtual int RoundId { get; set; }
    }
Apr 18, 2013 at 12:44 AM
Edited Apr 18, 2013 at 12:50 AM
Hi Gorizon,

I created a new module with your code, i run migrations and i found that both parts (OrganisationPart and ApplicationPart) were throwing nulls. So i just added to my project the driver and the handler for both parts and it worked! Just create a Drivers and Handlers folder and add this files:

ApplicationPartDriver.cs
using JetBrains.Annotations;
using Orchard;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Localization;
using Orchard.UI.Notify;
using System.Linq;
using Test.Models;

namespace Test.Drivers
{
     [UsedImplicitly]
    public class ApplicationPartDriver : ContentPartDriver<ApplicationPart>
    {
        protected override DriverResult Display(ApplicationPart part, string displayType, dynamic shapeHelper)
        {

            return ContentShape("Parts_ApplicationPart",
                () => shapeHelper.Parts_ContactusWidgetPart(ContentItem: part.ContentItem));
        }

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

        protected override DriverResult Editor(ApplicationPart part, IUpdateModel updater, dynamic shapeHelper)
        {
            if (updater.TryUpdateModel(part, Prefix, null, null))
            {
                
            }
            else
            {
                
            }
            return Editor(part, shapeHelper);
        }
    }
}
OrganisationPartDriver.cs
using JetBrains.Annotations;
using Orchard;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Localization;
using Orchard.UI.Notify;
using System.Linq;
using Test.Models;

namespace Test.Drivers
{
     [UsedImplicitly]
    public class OrganisationPartDriver : ContentPartDriver<OrganisationPart>
    {
        protected override DriverResult Display(OrganisationPart part, string displayType, dynamic shapeHelper)
        {

            return ContentShape("Parts_OrganisationPart",
                () => shapeHelper.Parts_OrganisationPart(ContentItem: part.ContentItem));
        }

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

        protected override DriverResult Editor(OrganisationPart part, IUpdateModel updater, dynamic shapeHelper)
        {
            if (updater.TryUpdateModel(part, Prefix, null, null))
            {
                
            }
            else
            {
                
            }
            return Editor(part, shapeHelper);
        }
    }
}
ApplicationPartHandler.cs
using JetBrains.Annotations;
using Orchard.ContentManagement.Handlers;
using Orchard.Data;
using Test.Models;


namespace Test.Handlers
{
    [UsedImplicitly]

    public class ApplicationPartHandler : ContentHandler
    {
        public ApplicationPartHandler(IRepository<ApplicationRecord> repository)
        {
            Filters.Add(StorageFilter.For(repository));
        }
    }
}
OrganisationPartHandler.cs
using JetBrains.Annotations;
using Orchard.ContentManagement.Handlers;
using Orchard.Data;
using Test.Models;


namespace Test.Handlers
{
    [UsedImplicitly]

    public class OrganisationPartHandler : ContentHandler
    {
        public OrganisationPartHandler(IRepository<OrganisationRecord> repository)
        {
            Filters.Add(StorageFilter.For(repository));
        }
    }
}
Please consider using the Orchard.Module.Szmyd.CodeGeneration
for generating the parts. You will get all the dirty stuff(ContentPart, ContentPartRecord, ContentPartDriver, ContentPartHandler, Views.. etc..) from only one command line!!

Let me know if this works in your project!

See ya!
Apr 18, 2013 at 12:57 PM
Thank a lot jusquiano.
You pulled me in the right direction. As I wrote in my first post OrganisationPart was fine (so it assumed that I've already got all stuff in place!) but the problem was with ApplicationPart only even I had driver and handler for it. I was checking the code between those parts and it was kind of identical.
Anyway I found the reason!
Application driver was excluded from the project somehow! And because I don't show it I have missed that fact.
Anyway during this journey I got some new knowledge about content types structure :)
Cheers
Apr 18, 2013 at 4:45 PM
It seems you solved the issue!

Cheers!