Tuesday, January 19, 2010

SharePoint Content Types Best Practices

I posted some SharePoint site content type guidelines back in 2008 and this post adds some detailed recommendations on the content type ID attribute and on the SourceID and Name attributes for content types fields.

I often create content types and site columns using the UI because it is simple and straight forward, and then use SharePoint Manager to get a starting point for the feature XML from the SchemaXml panel in SPM. It is just a starting point as you need to modify the XML for it to become valid CAML for defining site content types and site columns. I won't describe this mechanism in details, you can find help on this elsewhere.

You should at least make these changes for site columns:
Creating a new field GUID will ensure that your packaged site columns will not collide with the jump start fields when you activate your feature later on. For the same reason, I recommend prefixing all your jump start names with e.g. "dev" such as in "devContosoWebIngress".

You should at least make these changes for content types:
  • Keep only the fields you added to the content type (it will contain all inherited fields also) 
  • Update the <FieldRef> IDs to reflect the new GUIDs you created for your site columns
  • Create a new <ContentType> ID according to recommended practices (see more below)
  • If your content type ID really requires a new GUID, make sure it does not start or end with zero
ContentType IDs have two main formats, one based on GUIDs for your core content types and one based on simple two-digit numbering for variations on those core types. The core content types should be your immutable base types, while the variations are where the customizations are done. See my "open for extension, closed for modification" recommended Open-Closed practice.

Creating content types using the UI will always create a "core style" ID, even if you just make a content type variant. That is why you always should create a new ID for your custom content types, limiting the number or core content types and use the shorter "variant style" ID whenever possible. Let me explain using an example to show how to inherit a new custom core type "Generic Section Page" from the standard MOSS WCM "Page" type and then create two variations of the core custom type.

The Page type has this ID, called [page] later on:


Our new "Generic Section Page" core content type requires a registry format GUID with the {} and - removed. To inherit the Page content type you append 00 and the custom, stripped GUID to the Page ID to create a new core ID:


This core content type ID is analogous to a namespace in .NET code, it is a unique grouping of all content types that have this as their base ID.

Our new section page variants "Section Page A" and "Section Page B" needs no GUIDs, just their own two-digit number appended to the core type, but not the reserved 00 combination:


Note that 00 is a marker for inheritance between content types when the IDs are concatenated. Thus, I recommend that your custom content type GUIDs never start or end with zero, as this just makes it harder to know where a specific type starts or ends in an inheritance tree ID as it gets longer and longer. Just a simple thing. Still, looking at content type source feels like looking at the green rain of Matrix code.

[UPDATE] See Content Type IDs on MSDN published in May 2010.

As a side note, research suggests that you need no more than about five to ten core content types to classify and organize your content - just think of the library card taxonomies such as the Dewey Decimal Classification that has been used for centuries.

Regarding naming of site columns; the age old recommendation for SharePoint sites and lists is to create them first without any spaces or special characters in the title to set the name, and then rename the site or list afterwards to set the display title. The same applies to site columns, make sure that the Name attribute is without any spaces or special characters - apply your user friendliness skills to the DisplayName attribute.

If you use the above SchemaXml trick and don't follow the naming best practice, for "Contoso Web Ingress" you get "Contoso_x0020_Web_x0020_Ingress" as the Name. If you think that looks ugly, just wait until you do a rollup using the content query web-part (CQWP) and need to select that field in XSL - then your laziness will result in this:

<xsl:value-of select="@Contoso_x005F_x0020_Web_x005F_x0020_Ingress" />

In this case it would be better to put lipstick on the pig using the CQWP DataColumnRenames setting to rename the encoded name to what it should have been in the first place.

Note that not all underscores will get encoded into _x005F_ such as for the description field of standard SharePoint lists and doc-libs, which has the internal name _Comments. So if you use CQWP to fetch data from e.g. a custom list, it will still have the name _Comments in the item style XSL.

1 comment:

John Della Pietra said...

Thanks for the great post. Always good to see how others approach best practice in SharePoint. Looking forward to seeing how much this all changes in sharepoint 2010. Just started my SharePoint focused blog in earnest at http://sharepointjazz.blogspot.com