Can't Create Part

Topics: Writing modules
Mar 3, 2012 at 6:36 PM

I'm trying to write a simple module  that has an admin menu to create a new instance of my custom part. However, when the controller tries to create the instance I get an exception (Invalid Cast Exception) thrown by the 'New' method in the 'ContentExtensions.cs':

public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
  var contentItem = manager.New(contentType);
  if (contentItem == null)
      return null;

  var part = contentItem.Get<T>();
  if (part == null)
      throw new InvalidCastException();

  return part;
}

Here's my ContentPart:

    public class TermsPart : ContentPart<TermsRecord>
    {
        [Required]
        public string Terms
        {
            get { return this.As<BodyPart>().Text; }
            set { this.As<BodyPart>().Text = value; }
        }

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

And my ContentRecord:

    public class TermsRecord : ContentPartRecord
    {
        public virtual string Terms { get; set; }

        public virtual DateTime CreatedUtc { get; set; }
    }

And my migration:

    public int Create()
    {
        SchemaBuilder.CreateTable("TermsRecord",
            table => table
                .ContentPartRecord()
                .Column<DateTime>("CreatedUtc", c => c.NotNull())
        );

        ContentDefinitionManager.AlterTypeDefinition("Terms",
            cfg => cfg
                .WithPart("BodyPart")
        );
        return 1;
    }

As you can see, it's just meant to have a 'body part' and a 'date'. My controller successfully directs me to the admin 'create':
    public ActionResult Create()
    {
        // This is where it fails:
        var terms = _contentManager.New<TermsPart>("Terms");
        if (terms == null)
            return HttpNotFound();

         dynamic model = _contentManager.BuildEditor(terms);

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

 

Anybody know why I can't create a new 'blank' instance of my content type?

Developer
Mar 3, 2012 at 6:38 PM

Shouldn't you also attach the "TermsPart" to the "Terms" content type?

Mar 3, 2012 at 6:55 PM
Edited Mar 3, 2012 at 6:55 PM

That's the thing, this is my first stab, so I'm still confused! Trying to find a good simple walkthrough of creating a content type, with content part (the terminology still confuses me too!) - I'm still confused, even after following your excellent blog series!

I'll have a look again and see if I can make sense of your tip. Thanks.

Developer
Mar 3, 2012 at 7:07 PM

Yeah I know what you mean. I had difficulty in wrapping my head around the matter as well.

Remember: Content Types consist of Content Parts. It's these Content Parts that define the properties of a content type (just like a molecule is nothing without its atoms).

The only step that you seem to be missing is attaching the TermsPart to your Terms content type:

public int Create()
    {
        SchemaBuilder.CreateTable("TermsRecord",
            table => table
                .ContentPartRecord()
                .Column<DateTime>("CreatedUtc", c => c.NotNull())
        );

        ContentDefinitionManager.AlterTypeDefinition("Terms",
            cfg => cfg
                .WithPart("BodyPart")
                .WithPart("TermsPart")
        );
        return 1;
    }

 (notice the line in red).

 

Mar 3, 2012 at 7:16 PM

That worked!

Thanks! (I'll get the hang of it eventually!) Keep up the blog!

Developer
Mar 3, 2012 at 7:22 PM

Excellent. Yeah that's how it works: just keep doin it. I'll be sure to keep up the blog :)