You are hereBlogs / Niral's blog / Create a SharePoint Content Type programmatically

Create a SharePoint Content Type programmatically


Sometimes it is necessary to create a Sharepoint Content Type by code, specially when batch creating content types.  The following code snippet shows how a sharepoint content type can be created in C#.  I have also included some not-so-simple field types like choice and lookup.
using (SPSite p_site = new SPSite(urlToSite))
{
    using (SPWeb p_web = p_site.OpenWeb())
    {
        SPContentType CustomContentType = new
                SPContentType(p_web.AvailableContentTypes["ParentContentType"],
                p_web.ContentTypes, "MyContentType");
 
        // A string Field
        p_web.Fields.Add("NumberColumn", SPFieldType.Number);
        SPFieldLink fLink1 = new SPFieldLink(p_web.Fields["NumberColumn"]);
        CustomContentType.FieldLinks.Add(fLink1);
 
        // A required number field
        p_web.Fields.Add("StringColumn", SPFieldType.Text, true);
        SPFieldLink fLink2 = new SPFieldLink(p_web.Fields["StringColumn"]);
        CustomContentType.FieldLinks.Add(fLink2);
 
        //A Choice Field
        p_web.Fields.Add("ChoiceColumn", SPFieldType.Choice, false);
        SPFieldChoice choicefield = (SPFieldChoice)p_web.Fields["ChoiceColumn"];
        // Add a group to the filed
        choicefield.Group = "MyGroup";
        // Add choices
        choicefield.Choices.Add(string.Empty);
        choicefield.Choices.Add("Yes");
        choicefield.Choices.Add("No");
        // Set the default choice
        choicefield.DefaultValue = string.Empty;
        choicefield.Update();
        SPFieldLink fLink3 = new SPFieldLink(choicefield);
        CustomContentType.FieldLinks.Add(fLink3);
 
        p_web.Fields.Add("LookupColumn", SPFieldType.Lookup, false);
        SPFieldLookup lookupfield = (SPFieldLookup)p_web.Fields["LookupColumn"];
        // Set the remote lookup list
        lookupfield.LookupList = new Guid("guidofremotelist");
        // Set the remote field
        lookupfield.LookupField = "remotefieldname";
        lookupfield.Update();
        SPFieldLink fLink4 = new SPFieldLink(lookupfield);
        CustomContentType.FieldLinks.Add(fLink4);
        
        p_web.ContentTypes.Add(CustomContentType);
        CustomContentType.Update();
    }
}
When I try to update my content type (following this guide almost exactly) I get "A content type which does not belong to a collection cannot be updated" as a fatal error. This is thrown on SPContentType.Update(bool, bool) and through reflector I'm pretty sure this code block is throwing it: if ((this.Collection != null) && (this.Collection[this.Id] == null)){ throw new SPException(SPResource.GetString("CannotUpdateContentType", new object[0]));} the second condition of the if is the confusing/important part -- why would the SPContentTypeCollection of the web not being updated to include my new ContentType? I'm declaring the content type like this: SPContentType OSUMC_Item = new SPContentType(web.AvailableContentTypes["Item"], web.ContentTypes, "MyCType");
Steve, Add the following line: <code> p_web.ContentTypes.Add(CustomContentType); </code> before this line: <code> CustomContentType.Update(); </code> And it should work.   Good luck, Joe
Hi Joe, Thanks for pointing out my mistake.  I have updated the code to reflect your suggestion. Thanks, Niral
With respect to the Lookup section:  I get an error telling me to use the "AddLookup" method instead.  
hi, I am trying to add a lookup field to a calendar list which gets its data from another list on another site...The field is displayed, but the lookup field contains no values...? Can you please help me out? Thank you Regards Chris Sammut
Hi Chris, You are trying to get data from another site?  It it in the same Site Collection or a different one?  If you can paste some code, then I might be able to help out. -- Niral
You are trying to get data from another site?  It it in the same Site Collection or a different one?  If you can paste some code, then I might be able to help out.
With respect to the Lookup section:  I get an error telling me to use the "AddLookup" method instead.
I got the "use the AddLookup method instead" error too. Niral's code, while extremely helpful as a starting point (thank you!), should actually look like this for lookup fields:
site.Fields.AddLookup("LookupColumn", new Guid("guidofremotelist"), false);
SPFieldLookup newField = (SPFieldLookup)site.Fields["LookupColumn"];
...
Hope someone finds that useful.
Hi Lee, It is a very good note. Everything works fine while a lookup field and a target list are on the same site collection. Do you know if is there any way to provision a lookup field and a target lookup list (from which a lookup list gets the data) on the separate web applications ? Thanks