Create content type in Umbraco

Hi, this is one of my first posts on programming in Umbraco. And it's about programatically creating a content type and assigning the available child content types. It's actually pretty easy once you spend a day digging through code, so I figured I would share my knowledge.

To create the content type is pretty straight forward.

First, all of the using statements needed for this exercise.

using System.Collections.Generic;
using System.Linq;
using umbraco.interfaces;
using Umbraco.Core.Models;
using Umbraco.Core.Services;

Now to create the content type.

IContentTypeService contentTypeService = Umbraco.Core.ApplicationContext.Current.Services.ContentTypeService; //create the service
IContentType galleryContentType = new ContentType(-1); //create the content type. use a -1 to not create a tree. You can create a tree by passing in the id of the parent content type.
galleryContentType.Name = "the friendly name"; //set the display name of the content type
galleryContentType.Alias = "theprogramfriendlyname"; //set the actual name of the content type
contentTypeService.Save(galleryContentType); //save it

And that is all there is to creating a content type in Umbraco v6. Keep reading for properties and allowed child objects.

Now, we might ant to set some properties up on it though. These get a little tricky, you need the IDataTypeDefinition that will set the data type you want.

We'll need an IDataTypeService, the list of IDataTypeDefinitions that the system knows about, and to choose the correct one.

One interesting thing to note, is that it will check to see if the property exists before adding it. So you don't need to do that yourself. Cool right?

IDataTypeService dataTypeService = Umbraco.Core.ApplicationContext.Current.Services.DataTypeService;
IDataTypeDefinition[] dataTypeDefinitions = dataTypeService.GetAllDataTypeDefinitions().ToArray(); //.ToArray() because arrays are fast and easy.
IDataTypeDefinition definition = dataTypeDefinitions.FirstOrDefault(p => p.Name.ToLower() == "media picker"); //we want the media picker data type.
galleryContentType.AddPropertyGroup("Gallery"); //add a property group, not needed, but I wanted it
galleryContentType.AddPropertyType(new PropertyType(definition)
    {
        Name = "MediaItem",
        Alias = "MediaItem",
        Description = "Media item containing the images to display.",
        Mandatory = true
    }, "Image"); //create a mandatory property called MediaItem that will use the media picker to get it's data.
contentTypeService.Save(galleryContentType); //save the content type

And now we want to add a child data type. Lets pretend that I've created 2 datatypes, galleryContent and galleryCategoryContent. They would have been created using the same steps as above. The big issue I ran into is that the .AddContentType doesn't actually add the content type when it's saved. Which was no good. So I had to set the .AllowedContentTypes which did work. With that in mind, here we go

List types = new List(galleryContentType.AllowedContentTypes); //use a list so we can add the new item easily
if (types.Any(p => p.Id.Value == galleryCategoryContent.Id) == false) //check to see if the item exists
{
    //doesn't exist, add it
    ContentTypeSort sort = new ContentTypeSort(); //the ContentTypeSort is what is used
    sort.Alias = galleryCategoryContent.Alias; //set the alias of the sort to the new item
    sort.SortOrder = 0; //set the sort order to 0, this isn't really going to matter
    sort.Id = new System.Lazy(() => galleryCategoryContent.Id); //set the id. for whatever reason they used the System.Lazy to return the id which was kind of a pain.
    types.Add(sort); //add the item
    galleryContentType.AllowedContentTypes = types; //set the allowed content types to the new list
}
contentTypeService.Save(galleryContentType); //save it.

And that's it. We have now created 2 data types, one with a property, and assigned the second one as a possible child object to the first.