Orchard CMS: Adding a field to a custom content type in your module / migrations.cs

17 March 2013

While it sounds simple, I didn't quite find all the documentation I needed in once place, and there were a few gotchas, so I thought I'd make a post (if only for my own future reference).

A few notes on fields, content types and content parts before we continue:

  • When we add a field to a content type via the Admin Interface in Orchard, it looks nice and independent, but in the background all fields are tied to a Content Part; specifically, a Content Part that has the same name as the Content Type.
  • Fields aren't stored in the database directly, unlike the properties defined in your Model and handled by the driver for custom Content Parts.

So how do we go about adding a Content Field to your custom Content Type? Most of what you need for a custom content type is available on the Orchard Documentation site here - you can follow along and codegen a simple module. Within the migrations.cs for your module (which is run when your module is activated), you can then simply add fields to the content part of the same name (make sure you are adding fields to a content part with the same name as your content type or you will get weird mapping errors), then add the special content part to the content type.

Sample code:

namespace MyCustomModule {
    public class Migrations : DataMigrationImpl
    {

        public int Create()
        {
            //the part name has to match the Content Type name if you're adding Fields
            ContentDefinitionManager.AlterPartDefinition("CustomItem",           
              builder => builder
                            .WithField("MyLink", cfg => cfg
                                .OfType("LinkField")
                                .WithDisplayName("My Link"))                                                                                        
                            .WithField("Description", cfg => cfg
                                .OfType("TextField")
                                .WithDisplayName("Description")
                                .WithSetting("TextFieldSettings.Flavor", "html"))
                            );

            // add parts to ContentType
            ContentDefinitionManager.AlterTypeDefinition(
                "CustomItem"
                , cfg =>
                    cfg
                        .DisplayedAs("My Content Type")                        
                        .WithPart("TitlePart")
                        .WithPart("CustomItem")     //don't forget to add the part with the fields to your content type 
                        .WithPart("CommonPart")
                        .Draftable()
                        .Creatable()
            );

            return 1;
        }
    }
}

Note that you don't need to make a Model, or anything - the field data will persist for you automatically.

And a final note, that to set the flavor for the text field, you want to call .WithSetting("TextFieldSettings.Flavor", "html"), not .WithSetting("Flavor", "html") as mentioned in this StackOverflow question. I guess this is the price you pay when the development of Orchard moves so quick! (If you're wondering, the code is I used is valid for Orchard 1.6)

Hope this helps someone out there, it's not too hard once you get what you need to be doing, but it sure took me a while to get there.

Tags: content type, migrations, module, Orchard, fields

Add a Comment

2 Comments

  • Philip said Reply

    Thanks so much for this. I'm learning Orchard and I thought I figured out what I need to do for my first module. When I sat down to create a custom content type I realized I didn't know how to do it and all the documentation was only for creating custom content parts. Without this blog I was about to create a custom content part with fields, but now I see I can just create it in the Migration.