Creating Content Types
Applies to: SharePoint Foundation 2010
Available in SharePoint Online
As a developer, you create a content type by writing declarative XML or perhaps server code. This is usually something that you do as part of creating a Feature that someone else installs and still another person activates. Therefore, what you are really doing to a content type is not creating it but defining it.
Eventually, the Feature is installed and someone activates it. Microsoft SharePoint Foundation executes your code or reads your declarative XML and makes the content type available. An administrative user who has permission to manage lists applies the new content type to a list or document library, and it is in play. Any user who is allowed to add items to the list can use your content type to create content. Administrative users can modify the content type to suit themselves by adding or removing columns, or changing other attributes. All of that is out of your hands.
The key point, then, is that "creating" a content type really means creating a content type definition. A good content type definition anticipates how the content type is ultimately used.
Content Type Inheritance
You never create a content type from scratch. Instead, you always select an existing content type as the basis for any new content type that you create. This is exactly what Microsoft SharePoint Foundation does for its built-in content types. For information about the hierarchy of content types that are provided with SharePoint Foundation, see Base Content Type Hierarchy.
The website where a new content type is created must be in scope for the content type from which it is derived, so you should consider this when you write your content type definition. For more information, see Content Type Scope.
SharePoint Foundation supports a limited form of content type inheritance. When the Feature that defines a new content type is activated, columns and other metadata that are defined for the parent content type are passed on to the child content type. This is the only part of inheritance that is automatic.
Note
In earlier versions of SharePoint Foundation, columns and metadata that were added to a content type after it was provisioned were not inherited by child content types. In SharePoint Foundation 2010, this behavior has changed. You now have the option to include columns and metadata that users have added to the parent. For more information, see the description of the Inherits attribute on the ContentType element.
After a content type is made available and is being used, you or someone else can modify the definition for the parent content type, but that change is not automatically pushed down to derived content types. This aspect of inheritance must be initiated manually, either through the user interface or in custom code. For more information, see Updating Child Content Types.
However, content type inheritance does allow you to work with content types much as you would with derived classes. For example, just as you can override properties of a base class, you can modify attributes that your content type derives from its parent content type. You can add, alter, or remove columns; specify different New, Edit, or Display forms; specify a different document template; and so on. What this means, then, is that you can create base content types just as you create base classes in developing an application framework. For example, you could define a content type named Financial Document with characteristics common to all financial documents in your organization. You could then use Financial Document as the basis for new content types, such as Invoice and Purchase Order. The new content types inherit columns and other metadata from Financial Document, so you define common elements only once, on the parent content type.
You can get ideas for building your own content type hierarchy by studying how SharePoint Foundation uses inherited attributes of base content types, and how it modifies them. A good place to start is with the content type gallery in the user interface. On the Site Actions menu, select Site Settings. On the Site Settings page, under Galleries, click Site content types. On the Site Content Types page, click the link for an interesting content type.
Another good resource for study is the file ctypewss.xml in the folder %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\FEATURES\ctype. This file contains the definitions for many of the built-in content types. For help in understanding the definitions see Content Type Definitions.
Designing Content Types
For a comprehensive guide to planning content types, see Planning content types and workflows. The following are some general considerations:
Scope. Where in the site hierarchy do you want the content type to become available?
If the content type should be available throughout an entire site collection, you should deploy it in a Feature with site collection scope and write code in the FeatureActivated method of a feature receiver class that adds the content type to the root website's content type collection.
Parent. Which existing content type that is in scope will you choose to derive your content type from?
Your content type will not activate correctly if the parent content type is not available in the website where your content type is created.
Columns. Which existing site columns are available for you to use?
Columns that are not inherited from the parent content type must be added. Columns that do not exist must be created.
Other Resources. Will the content type require language resources? Document templates? Forms?
If the content type requires any of these resources, you must know how they will be provisioned and how the content type will access them.
Creating a Content Type Using Declarative XML
One way to create a content type is to use declarative XML to define the content type in the element manifest file for a Feature. When the Feature is activated, the content type is created. For more information, see Content Type Definitions and Using Features in SharePoint Foundation.
You can define several content types in the same element manifest file. Include a ContentType element for each content type that you define. The ID attribute is required, and the value that you specify must follow a very specific format. A correctly formatted content type ID identifies not only the new content type but also its parent content type. For more information, see Content Type IDs.
To create an ID for a content type that is derived from a built-in content type, start with the hexadecimal string that identifies the built-in content type, append two zeros, and then add a GUID with all the punctuation removed. For example, the hexadecimal string that identifies the Item content type is "0x01". The ID for a content type that derives from Item should look something like the following:
0x0100A33D9AD9805788419BDAAC2CCB37509F
To create IDs for additional content types that inherit from your content type, append "01", "02", and so on.
Another required attribute of the ContentType element is Name, which specifies a display name. The value can be a reference to a resource in the format $Resources:String. For more information, see Localizing SharePoint Solutions. The name itself cannot be longer than 128 characters and cannot contain the characters \ / : * ? " # % < > { } | ~ &, two consecutive periods (..), or special characters, such as a tab.
When you include columns in a content type, you do not create them in the content type definition. Instead, you reference columns that have been created elsewhere. To include a column reference, add a FieldRef element as a child of the ContentType element. The referenced column can be one that already exists as a site column or a new column created by the same Feature that creates the content type. For information about creating site columns, see Field Definitions.
You can also use the FieldRef element to reference a column that the content type inherits from its parent content type. In this case, your reason for referencing the column would not be add the column but to change some of its characteristics when it is used in the content type.
The ID attribute of the FieldRef element identifies the column that you are referencing. The value should be the string representation of a GUID, including braces. The value is case-sensitive.
Tip
You can find the IDs for built-in fields in the file fieldswss.xml located on the following path: %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\FEATURES\fields.
If your content type uses a document template for new content, you can identify it in a DocumentTemplate element within the ContentType element. You must provision the file separately. One way to do that would be to add a Module element to the manifest and include the file with the Feature. For more information, see How to: Provision a File.
The content type definition can also include definitions for custom forms through an XMLDocuments element. For more information, see Custom Information in Content Types.
Example
The following example shows the element manifest for a Feature that creates four site columns and three site content types. The first content type, Financial Document, is a child of the built-in Document content type. The remaining two new content types, Invoice and Purchase Order, both derive from Financial Document.
The definition for Financial Document references two of the new site columns, DateOpened and Amount. The FieldRef element that references the DateOpened column sets the DisplayName attribute so that the column name will render as "Date" instead of "Date Opened" as defined in the site column.
The Invoice content type is the first of two new content types that derive from Financial Document. The definition for the content type references a third new site column, Client, and sets the Required attribute to TRUE so that an entry is required for this field when a new item is created. The Invoice type includes a FieldRef element for the Title column, even though it is inherited, in order to change the value of the DisplayName attribute from "Title" to "Service".
The second content type that derives from Financial Document is Purchase Order. The definition for the content type references a fourth new site column, CostCenter, and sets the DisplayName attribute so that the column name will render as "Department" instead of "Cost Center" as it is defined in the site column.
Purchase Order inherits the column references from its parent, Financial Document, so you do not have to reference them again. The content type also inherits a reference to the Title column from Financial Document, which inherits the column from its parent, Document. The Purchase Order type includes a FieldRef element for the Title column in order to override the inherited DisplayName attribute with a value of its own.
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="https://schemas.microsoft.com/sharepoint/">
<!-- Document Templates -->
<Module Name="InvoiceDocumentTemplate"
Path="FinancialDocuments"
Url="_cts/Invoice" RootWebOnly="TRUE">
<File Url="Invoice.docx" Type="Ghostable" />
</Module>
<Module Name="PurchaseOrderDocumentTemplate"
Path="FinancialDocuments"
Url="_cts/PurchaseOrder" RootWebOnly="TRUE">
<File Url="PurchaseOrder.docx" Type="Ghostable" />
</Module>
<!-- Site Columns -->
<Field ID="{060E50AC-E9C1-4D3C-B1F9-DE0BCAC300F6}"
Name="Amount"
DisplayName="Amount"
Type="Currency"
Decimals="2"
Min="0"
Required="FALSE"
Group="Financial Columns" />
<Field ID="{86811853-7E52-4515-A88D-A8FA9D450905}"
Name="Client"
DisplayName="Client Name"
Type="Text"
Required="FALSE"
Group="Financial Columns"/>
<Field ID="{1511BF28-A787-4061-B2E1-71F64CC93FD5}"
Name="DateOpened"
DisplayName="Date Opened"
Type="DateTime"
Format="DateOnly"
Required="FALSE"
Group="Financial Columns">
<Default>[today]</Default>
</Field>
<Field ID="{943E7530-5E2B-4C02-8259-CCD93A9ECB18}"
Name="CostCenter"
DisplayName="Department"
Type="Choice"
Required="FALSE"
Group="Financial Columns">
<CHOICES>
<CHOICE>Administration</CHOICE>
<CHOICE>Information</CHOICE>
<CHOICE>Facilities</CHOICE>
<CHOICE>Operations</CHOICE>
<CHOICE>Sales</CHOICE>
<CHOICE>Marketing</CHOICE>
</CHOICES>
</Field>
<!-- Site Content Types -->
<!-- Parent ContentType: Document (0x0101) -->
<ContentType ID="0x0101000728167cd9c94899925ba69c4af6743e"
Name="Financial Document"
Group="Financial Content Types"
Description="Base financial content type"
Version="0">
<FieldRefs>
<FieldRef ID="{1511BF28-A787-4061-B2E1-71F64CC93FD5}" Name="DateOpened" DisplayName="Date" Required="TRUE"/>
<FieldRef ID="{060E50AC-E9C1-4D3C-B1F9-DE0BCAC300F6}" Name="Amount" DisplayName="Amount" Required="FALSE"/>
</FieldRefs>
</ContentType>
<!-- Parent ContentType: Financial Document -->
<ContentType ID="0x0101000728167cd9c94899925ba69c4af6743e01"
Name="Invoice"
Group="Financial Content Types"
Description="Used for creating customer invoices"
Inherits="TRUE"
Version="0">
<FieldRefs>
<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" DisplayName="Service" Required="TRUE" Sealed="TRUE"/>
<FieldRef ID="{86811853-7E52-4515-A88D-A8FA9D450905}" Name="Client" DisplayName="Client Name" Required="TRUE"/>
</FieldRefs>
<DocumentTemplate TargetName="Invoice.docx" />
</ContentType>
<!-- Parent ContentType: Financial Document -->
<ContentType ID="0x0101000728167cd9c94899925ba69c4af6743e02"
Name="PurchaseOrder"
Group="Financial Content Types"
Description="Used for creating purchase orders"
Inherits="TRUE"
Version="0">
<FieldRefs>
<FieldRef ID="{fa564e0f-0c70-4ab9-b863-0177e6ddd247}" Name="Title" DisplayName="Item" Required="TRUE" Sealed="TRUE"/>
<FieldRef ID="{943E7530-5E2B-4C02-8259-CCD93A9ECB18}" Name="CostCenter" DisplayName="Department" Required="TRUE"/>
</FieldRefs>
<DocumentTemplate TargetName="PurchaseOrder.docx"/>
</ContentType>
</Elements>
Creating a Content Type Using Code
As an alternative to using declarative XML to create a content type, you can use the SharePoint Foundation object model. Typically, declarative XML is easier to write. However, declarative XML generally offers less flexibility than the object model, which has access to the capabilities of the entire Microsoft .NET Framework and can be debugged at run time. Both approaches are supported by templates provided with SharePoint development tools in Microsoft Visual Studio 2010.
Place the code that defines your content type in the FeatureActivated method of a subclass of the SPFeatureReceiver class.
You create a content type by calling the constructor for the SPContentType class. Before you call the constructor, you must gather three items to pass as arguments:
An SPContentType object that represents the parent content type.
You can retrieve this object from the collection returned in the AvailableContentTypes property of the SPWeb object that represents the website where you are creating your content type.
An SPContentTypeCollection object that represents the collection for the website where you are creating the content type.
You can get this object by accessing the ContentTypes property of the SPWeb object that represents the website where you are creating the content type.
A string that contains the name that you want to give the content type.
The name that you provide is used as the content type's display name. Some characters are not allowed in content type names. You can validate your proposed name by calling the static method ValidateName(String). This method checks for illegal characters but does not check for duplicate names.
After you call the constructor to create a new SPContentType object, you must add it to the website's content type collection in a separate call to the Add(SPContentType) method of the SPContentTypeCollection object that represents the website's collection. This step completes initialization of the content type.
Warning
The Add(SPContentType) method throws an SPException exception if a content type with the same name already exists in the collection.
If you intend to set properties of the content type, you should save the SPContentType object that is returned by the Add method.
You can add columns to the content type by referencing each column in an SPFieldLink object. Then call the Add(SPFieldLink) method of the SPFieldLinkCollection object that is returned by the content type's FieldLinks property.
When you have completed the content type's configuration, call the Update() method to commit the changes to the database.
Example
The following example creates exactly the same site columns and content types as are created by the previous example. The only difference is that instead of using declarative XML, this example uses code in the FeatureActivated method of a feature receiver.
The properties parameter of the FeatureActivated method is a SPFeatureReceiverProperties object. The Feature property of this object returns an SPFeature object that has a Parent property that contains a boxed SPSite object or a boxed SPWeb object. You should not dispose of these objects. However, you should dispose of any new SPWeb or SPSite objects that your code creates. For more information, see Disposing Objects.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = null;
if (properties.Feature.Parent is SPSite)
{
SPSite sites = (SPSite)properties.Feature.Parent;
web = sites.RootWeb;
}
else
{
web = (SPWeb)properties.Feature.Parent;
}
if (web == null)
return;
/* CREATE SITE COLUMNS */
string columnGroup = "Financial Columns";
// Amount
string amountFieldName = web.Fields.Add("Amount", SPFieldType.Currency, false);
SPFieldCurrency amountField = (SPFieldCurrency)web.Fields.GetFieldByInternalName(amountFieldName);
amountField.Group = columnGroup;
amountField.DisplayFormat = SPNumberFormatTypes.TwoDecimals;
amountField.MinimumValue = 0;
amountField.Update();
// Client Name
string clientFieldName = web.Fields.Add("Client Name", SPFieldType.Text, false);
SPFieldText clientField = (SPFieldText)web.Fields.GetFieldByInternalName(clientFieldName);
clientField.Group = columnGroup;
clientField.Update();
// Date Opened
string dateOpenedFieldName = web.Fields.Add("Date Opened", SPFieldType.DateTime, false);
SPFieldDateTime dateOpenedField = (SPFieldDateTime)web.Fields.GetFieldByInternalName(dateOpenedFieldName);
dateOpenedField.Group = columnGroup;
dateOpenedField.DisplayFormat = SPDateTimeFieldFormatType.DateOnly;
dateOpenedField.DefaultValue = "[today]";
dateOpenedField.Update();
// Cost Center Name
string costCenterFieldName = web.Fields.Add("Cost Center", SPFieldType.Choice, false);
SPFieldChoice costCenterField = (SPFieldChoice)web.Fields.GetFieldByInternalName(costCenterFieldName);
costCenterField.Choices.Add("Administration");
costCenterField.Choices.Add("Information Services");
costCenterField.Choices.Add("Facilities");
costCenterField.Choices.Add("Operations");
costCenterField.Choices.Add("Sales");
costCenterField.Choices.Add("Marketing");
costCenterField.Group = columnGroup;
costCenterField.Update();
/* CREATE SITE CONTENT TYPES */
string contentTypeGroup = "Financial Content Types";
// Get a content type to be the parent of a new Financial Document content type.
SPContentType documentCType = web.AvailableContentTypes[SPBuiltInContentTypeId.Document];
// Create the Financial Document content type.
SPContentType financialDocumentCType = new SPContentType(documentCType, web.ContentTypes, "Financial Document");
// Note: A content type is not initialized until after it is added.
financialDocumentCType = web.ContentTypes.Add(financialDocumentCType);
financialDocumentCType.Group = contentTypeGroup;
// Add the Date Opened column. Child content types inherit the column.
SPFieldLink dateOpenedFieldRef = new SPFieldLink(dateOpenedField);
dateOpenedFieldRef.Required = true;
financialDocumentCType.FieldLinks.Add(dateOpenedFieldRef);
// Add the Amount column. Child content types inherit the column.
SPFieldLink amountFieldRef = new SPFieldLink(amountField);
financialDocumentCType.FieldLinks.Add(amountFieldRef);
// Commit changes.
financialDocumentCType.Update();
// Create the Invoice content type.
SPContentType invoiceCType = new SPContentType(financialDocumentCType, web.ContentTypes, "Invoice");
invoiceCType = web.ContentTypes.Add(invoiceCType);
invoiceCType.Group = contentTypeGroup;
// Modify the Title column inherited from the parent.
SPFieldLink serviceFieldRef = invoiceCType.FieldLinks[SPBuiltInFieldId.Title];
serviceFieldRef.DisplayName = "Service";
serviceFieldRef.Required = true;
// Add the Client column.
SPFieldLink clientFieldRef = new SPFieldLink(clientField);
clientFieldRef.Required = true;
invoiceCType.FieldLinks.Add(clientFieldRef);
// Specify a document template.
invoiceCType.DocumentTemplate = "Invoice.docx";
// Commit changes.
invoiceCType.Update();
// Create the Purchase Order content type.
SPContentType purchaseOrderCType = new SPContentType(financialDocumentCType, web.ContentTypes, "Purchase Order");
purchaseOrderCType = web.ContentTypes.Add(purchaseOrderCType);
purchaseOrderCType.Group = contentTypeGroup;
// Modify the Title column inherited from the parent.
SPFieldLink itemFieldRef = purchaseOrderCType.FieldLinks[SPBuiltInFieldId.Title];
itemFieldRef.DisplayName = "Item";
itemFieldRef.Required = true;
// Add the Department column.
SPFieldLink departmentFieldRef = new SPFieldLink(costCenterField);
departmentFieldRef.DisplayName = "Department";
departmentFieldRef.Required = true;
purchaseOrderCType.FieldLinks.Add(departmentFieldRef);
// Specify a document template.
purchaseOrderCType.DocumentTemplate = "PurchaseOrder.docx";
// Commit changes.
purchaseOrderCType.Update();
}
Public Overrides Sub FeatureActivated(ByVal properties As Microsoft.SharePoint.SPFeatureReceiverProperties)
Dim web As SPWeb = Nothing
If TypeOf properties.Feature.Parent Is SPSite Then
Dim sites As SPSite = DirectCast(properties.Feature.Parent, SPSite)
web = sites.RootWeb
Else
web = DirectCast(properties.Feature.Parent, SPWeb)
End If
If web Is Nothing Then
Return
End If
' CREATE SITE COLUMNS
Dim columnGroup As String = "Financial Columns"
' Amount
Dim amountFieldName As String = web.Fields.Add("Amount", SPFieldType.Currency, False)
Dim amountField As SPFieldCurrency = DirectCast(web.Fields.GetFieldByInternalName(amountFieldName), SPFieldCurrency)
amountField.Group = columnGroup
amountField.DisplayFormat = SPNumberFormatTypes.TwoDecimals
amountField.MinimumValue = 0
amountField.Update()
' Client Name
Dim clientFieldName As String = web.Fields.Add("Client Name", SPFieldType.Text, False)
Dim clientField As SPFieldText = DirectCast(web.Fields.GetFieldByInternalName(clientFieldName), SPFieldText)
clientField.Group = columnGroup
clientField.Update()
' Date Opened
Dim dateOpenedFieldName As String = web.Fields.Add("Date Opened", SPFieldType.DateTime, False)
Dim dateOpenedField As SPFieldDateTime = DirectCast(web.Fields.GetFieldByInternalName(dateOpenedFieldName), SPFieldDateTime)
dateOpenedField.Group = columnGroup
dateOpenedField.DisplayFormat = SPDateTimeFieldFormatType.DateOnly
dateOpenedField.DefaultValue = "[today]"
dateOpenedField.Update()
' Cost Center Name
Dim costCenterFieldName As String = web.Fields.Add("Cost Center", SPFieldType.Choice, False)
Dim costCenterField As SPFieldChoice = DirectCast(web.Fields.GetFieldByInternalName(costCenterFieldName), SPFieldChoice)
costCenterField.Choices.Add("Administration")
costCenterField.Choices.Add("Information Services")
costCenterField.Choices.Add("Facilities")
costCenterField.Choices.Add("Operations")
costCenterField.Choices.Add("Sales")
costCenterField.Choices.Add("Marketing")
costCenterField.Group = columnGroup
costCenterField.Update()
' CREATE SITE CONTENT TYPES
Dim contentTypeGroup As String = "Financial Content Types"
' Get a content type to be the parent of a new Financial Document content type.
Dim documentCType As SPContentType = web.AvailableContentTypes(SPBuiltInContentTypeId.Document)
' Create the Financial Document content type.
Dim financialDocumentCType As New SPContentType(documentCType, web.ContentTypes, "Financial Document")
' Note: A content type is not initialized until after it is added.
financialDocumentCType = web.ContentTypes.Add(financialDocumentCType)
financialDocumentCType.Group = contentTypeGroup
' Add the Date Opened column. Child content types inherit the column.
Dim dateOpenedFieldRef As New SPFieldLink(dateOpenedField)
dateOpenedFieldRef.Required = True
financialDocumentCType.FieldLinks.Add(dateOpenedFieldRef)
' Add the Amount column. Child content types inherit the column.
Dim amountFieldRef As New SPFieldLink(amountField)
financialDocumentCType.FieldLinks.Add(amountFieldRef)
' Commit changes.
financialDocumentCType.Update()
' Create the Invoice content type.
Dim invoiceCType As New SPContentType(financialDocumentCType, web.ContentTypes, "Invoice")
invoiceCType = web.ContentTypes.Add(invoiceCType)
invoiceCType.Group = contentTypeGroup
' Modify the Title column inherited from the parent.
Dim serviceFieldRef As SPFieldLink = invoiceCType.FieldLinks(SPBuiltInFieldId.Title)
serviceFieldRef.DisplayName = "Service"
serviceFieldRef.Required = True
' Add the Client column.
Dim clientFieldRef As New SPFieldLink(clientField)
clientFieldRef.Required = True
invoiceCType.FieldLinks.Add(clientFieldRef)
' Specify a document template.
invoiceCType.DocumentTemplate = "Invoice.docx"
' Commit changes.
invoiceCType.Update()
' Create the Purchase Order content type.
Dim purchaseOrderCType As New SPContentType(financialDocumentCType, web.ContentTypes, "Purchase Order")
purchaseOrderCType = web.ContentTypes.Add(purchaseOrderCType)
purchaseOrderCType.Group = contentTypeGroup
' Modify the Title column inherited from the parent.
Dim itemFieldRef As SPFieldLink = purchaseOrderCType.FieldLinks(SPBuiltInFieldId.Title)
itemFieldRef.DisplayName = "Item"
itemFieldRef.Required = True
' Add the Department column.
Dim departmentFieldRef As New SPFieldLink(costCenterField)
departmentFieldRef.DisplayName = "Department"
departmentFieldRef.Required = True
purchaseOrderCType.FieldLinks.Add(departmentFieldRef)
' Specify a document template.
purchaseOrderCType.DocumentTemplate = "PurchaseOrder.docx"
' Commit changes.
purchaseOrderCType.Update()
End Sub
See Also
Tasks
How to: Reference a Column in a Content Type
How to: Add a Content Type to a Site
How to: Add a Content Type to a SharePoint List
Concepts
Other Resources
Planning content types and workflows
Create Custom Content Types in SharePoint 2010
Walkthrough: Create a Custom Field, Content Type, List Definition, and List Instance