CategoriesOrchard

Creating Content Fields Programmatically in Orchard

One of the most compelling features of Orchard is its strong support for building and managing Content Types right out of the box through the Admin UI.  However, there will almost certainly be times when you want to create Content Types programmatically.  Maybe you are looking to package the Content Types into a reusable plugin, or maybe you just want more control and structure over what gets built on your site.  Whatever the reason, building Content Types programmatically is actually pretty easy.

The Content Type system in Orchard is an expansive topic, so we will be focusing on only one aspect of it in this post.  Specifically, we are going to look at how to add the built in Content Fields to Content Types programmatically. This topic isn’t all that complicated, but the syntax can be confusing and documentation is a bit sparse if you’re looking for info on every Field type.  I am going to show code examples for a few types of field you can add to a Content Type, and then I will show you how to figure out the syntax for all the other types on your own.

Another small note: You can also create Content Fields and Content Parts in Orchard that are backed by strongly typed classes and database entries you define using custom schemas.  These types of Content Fields and Content Parts are useful if you want to add in some kind of custom logic when items are saved or retrieved, among other benefits.  However, in a lot of cases you just want to save and display the information directly entered by the user.  In these situations you simply need to tell Orchard what types of fields you want (what we are doing in this post) and it will handle the rest for you.  If none of that makes sense to you yet, don’t worry about it – you will know when you encounter a situation that requires Content Fields backed by logic.

Anyway, onto the task at hand!

It’s important to remember that all Content Types in Orchard are simply a collection of Content Parts.  Content Parts are pieces of functionality such as Comments, Reviews, Publishing Options, and other bits that collectively define a Content Type.  For example, Comments are relevant to both blog posts as well as products on an ecommerce store.  However, an ecommerce product might also have shipping information or a collection of images associated with it.  It’s not one specific function that defines a Content Type – it’s a group of functionality.  The same concept applies to Content Parts themselves – these pieces of functionality are defined by a collection of smaller Content Fields.  For example, a Comments Content Part might have two text fields for the user’s email and message, along with an image field for their profile pic.

All Content Fields in Orchard must be attached to a Content Part – no exceptions! (or it might throw an exception…hah)  Yes, the Orchard UI lets you add Content Fields “directly” to a Content Type, but behind the scenes Orchard is really just attaching them to a Content Part it creates with the same name as the Content Type.

Go ahead and open up the Orchard solution in Visual Studio.   We also need to create a test module, so open the command line utility included in the bin folder of Orchard.web.  Run the command “codegen module YourModuleName” to create the module.  In order to use the codegen feature you have to enable it either through the Orchard admin or through the command line utility.  You may need to include the project in your Visual Studio solution after you run the command.  Next run the command “codegen datamigration YourModuleName” to create a migrations.cs class, which we will use for working with Content Types.

I realize I’m sort of skimming over this command line/module creation process, but it’s basic Orchard development so if you want to learn more check out the documentation here.

Let’s start with a simple example of creating a Content Field – the Boolean Field. Inside your module’s migrations.cs file, add the code below:

public int Create() {
            ContentDefinitionManager.AlterPartDefinition(
                "SamplePart",
                b => b
                .WithField("SampleBooleanField", f => f
                    .OfType("BooleanField").WithDisplayName("Sample Boolean Field")
                    .WithSetting("BooleanFieldSettings.Hint""Choose Wisely").WithSetting("BooleanFieldSettings.Optional""True")
                    .WithSetting("BooleanFieldSettings.NotSetLabel""Indecisive").WithSetting("BooleanFieldSettings.OnLabel""Yes")
                    .WithSetting("BooleanFieldSettings.OffLabel""No").WithSetting("BooleanFieldSettings.SelectionMode""Radiobutton")
                    .WithSetting("BooleanFieldSettings.DefaultValue""True")));
            return 1;
        }

This code creates a Content Part called Sample and assigns a Boolean Field to it.  As you can see, even the Boolean Field has a large number of options, but the settings are pretty straight forward.  Let’s look at a couple more examples that are a bit more cryptic, such as the enumeration field.  This field can be used to create drop downs or choices for the user.

public int UpdateFrom1() {
            ContentDefinitionManager.AlterPartDefinition(
                "SamplePart",
                b => b
                .WithField("SampleEnumField", f => f
                    .OfType("EnumerationField").WithDisplayName("Sample Enum Field")
                    .WithSetting("EnumerationFieldSettings.Hint""Choose your favorites!").WithSetting("EnumerationFieldSettings.Required""True")
                    .WithSetting("EnumerationFieldSettings.Options""Red
Green
Blue
Yellow")
                    .WithSetting("EnumerationFieldSettings.ListMode""Checkbox")));
            return 2;
        }

As shown above, the enumeration field has a setting called Options that requires a list of items.  These should be separated by the symbol 
 which create a carriage return.  Orchard does this for you automatically when you enter choices through the UI, but it can be confusing as to how you’re supposed to just “know” this.  We’ll look at how to figure this out in a moment.

Onto another Field – the Media Library Picker!  I have seen a few questions out there asking how to add this programmatically.  Here it is:

public int UpdateFrom2()
        {
            ContentDefinitionManager.AlterPartDefinition(
                "SamplePart",
                b => b
                .WithField("ImageField", f => f
                    .OfType("MediaLibraryPickerField").WithDisplayName("Sample Image Field")
                    .WithSetting("MediaLibraryPickerField.Hint""Images everywhere!").WithSetting("MediaLibraryPickerFieldSettings.Required""True")
                    .WithSetting("MediaLibraryPickerFieldSettings.Multiple""False")));
            return 3;
        }

Again, pretty straight forward once you know the syntax.

Let’s add another block of code to attach our Sample Content Part to a Content Type called “Test” so that we can actually see our results in the Admin area.

public int UpdateFrom3() {
            ContentDefinitionManager.AlterTypeDefinition(
                "Test",
                b => b
                .WithPart("SamplePart")
                .WithPart("CommonPart")
                );
 
            return 4;
        }

Run the Visual Studio Solution to bring up your dev site and then enable your module from the Admin.  Next, navigate to the Test Content Type we created (under Content Definition).  You can see our Sample Content Part is attached – expand it to see our Fields already pre-configured with the settings we defined.

Orchard-Content-Type-Example

So yes, I could walk through every field type and show you the complete syntax, but there is a better way to learn.  You can discover all of this for yourself using the database.  Looking into the Orchard database is a great way to figure out how certain things are setup.

Before we can look at the database we have to make sure there are entries relevant to what we are trying to discover.  Using the Orchard UI, create a new content type and assign a new Media Library Picker Field and a new Enumeration Field to it.  Play around with the settings for each and hit save.  If you’ve been following along via code you could also probably use the items we just created.

Now open up your database in SQL Server and browse to the table called dbo.Settings_ContentPartfieldDefinitionrecord.  This table contains information about all the fields that are assigned to content parts.  Under the Settings column you will see some XML that shows all of the settings for the fields you just created.  This column tells you everything you know to build out these fields programmatically.  For example, An image field might have an XML attribute “MediaLibraryPickerFieldSettings.Required=True”.  This corresponds directly to the “WithSetting()” method we were using earlier to assign these attributes.

Orchard-Content-Field-Definition

Now that you know how this works, in order to find out how to build any type of field programmatically, all you have to do is create a test version of it through the UI and then analyze what actually gets stored in the database.  This concept can apply to other aspects of Orchard, such as figuring out settings for Content Parts and Content Items.