Invalid cast when create content item with 2 parts

Topics: Customizing Orchard
Jun 3, 2011 at 10:51 AM

Yesterday i got a problem when creating content item from a content type with 2 parts . Here is details

I have 2 parts : NodePart , AddressPart . 

Migration file:

 

ContentDefinitionManager.AlterTypeDefinition("Node", cfg => cfg.WithPart("NodePart").WithPart("AddressPart"));

HttpGet Create method:

public ActionResult NodeCreate()
        {
            if (!Services.Authorizer.Authorize(Permissions.CompanyOwner, T("Not authorized to manage node types")))
                return new HttpUnauthorizedResult();

            var node = Services.ContentManager.New<INode>("Node");   ----> Error here
            var nodeModel = new NodeViewModel() {
                NodeTypes = _nodeService.GetNodeTypes(),
                Items = _nodeService.GetNodes(0)
            };
            var editor = Shape.EditorTemplate(TemplateName: "Parts/Node.Create", Model: nodeModel, Prefix: null);
            editor.Metadata.Position = "2";
            dynamic model = Services.ContentManager.BuildEditor(node);
            model.Content.Add(editor);

            // Casting to avoid invalid (under medium trust) reflection over the protected View method and force a static invocation.
            return View((object)model);
        }


 

The INode.cs : just an interface assignable from NodePart

 

public interface INode : IContent
    {
        string Name { get; }
        NodeTypePartRecord NodeType { get; }
        bool HasAddress { get; }
    }

 

The NodePart.cs

public class NodePart : ContentPart, INode
{
..........
}


Here is the error from : line 37 , Orchard.ContentManagement ContentItem.cs

 

public IContent Get(Type partType) {
            if (partType == typeof(ContentItem))
                return this;
            return _parts.FirstOrDefault(part => partType.IsAssignableFrom(part.GetType()));
        }

 

When I debugg the code , the _parts above contains 3 parts : ContentPart, AddressPart , StoragePart . The Storagepart is auto add-in , the AddressPart works normaly , the problem is that the ContentPart must be NodePart , but it's not , the partType is NodePart , and the part.GetType() is ContentPart (doesnt count the AddressPart and StoragePart) , so it is not assignable from ContentPart

Anyone have a solution :(

Jun 3, 2011 at 11:48 AM

I don't think it's proper to use New<T> with an interface; because the interface could be used multiple times and the content manager wouldn't know which one to create. Just use New("Node") instead. Also your content type needs CommonPart for it to behave properly in all situations.

Jun 3, 2011 at 11:54 AM

Thanks for reply , I tried to use New("Node") too , but it's not working , because

 var node = Services.ContentManager.New("Node"); --->will result a ContentItem , not NodePart

Also , I have tried :

var node = Services.ContentManager.New<NodePart>("Node");

but it still results an error about Specified cast is invalid

Jun 3, 2011 at 12:14 PM

Yep; ContentManger.New will create a content item, whatever you pass into it. But it will have NodePart. You can do:

using Orchard.ContentManagement;

 var item = Services.ContentManager.New("Node");
 var node = item.As<NodePart>();
ContentItems are just collections of parts. If you want to create a database table without it being part of a content item, don't use ContentPart - use an IRepository<TRecord> pattern.

Jun 4, 2011 at 4:32 AM

I have tried

var node = item.As<NodePart>();

but the _parts still contain a ContentPart , not a NodePart I need , so it will result a null object reference exception

Jun 4, 2011 at 4:55 AM

In that case you could be missing either a Driver or a Handler, have you got both of them?

Jun 4, 2011 at 5:23 AM

I got handler file , but I'm currently not using driver . I did this once wit another type that have only one part , but this time is 2 parts , don't know if it cause this problem

Jun 4, 2011 at 5:30 AM
Edited Jun 4, 2011 at 5:42 AM

Oh i found it , just create an empty driver for NodePart . But why in UserPart , I don't see any Driver ?

Jun 4, 2011 at 5:49 AM

Yeah, UserPart confuses me as well. Not sure exactly how it works without a driver but there must be something else it's doing. Actually I already raised an issue on this topic (http://orchard.codeplex.com/workitem/17883) - it's pretty counterintuitive that it works differently to other parts, but basically it's just old code written before drivers existed.