SharePoint Online Content Type Hub Publishing Issues

We use the SharePoint Online Content Type Hub extensively as the central location to create, manage and distribute content types throughout our SharePoint Online tenant. We recently saw an issue with the distribution of one of the content types defined in the Content Type Hub which had a specific PowerPoint template assigned to it.

The content type in question had been updated with a revised template and republished, however when we tried to create a new presentation from the content type in SharePoint Online, the older template was still being served. I spent quite a long time testing a variety of PowerPoint template files of varying content and sizes with the content type (upload a new template to the content type in the Content Type Hub –> republish the content type –> wait for distribution to the site collections –> test; a process that can take some time when the content type is being distributed correctly) with no progress at all. It didn’t seem to matter what template file I uploaded to the content type, nothing seemed to be distributed. I even tried a blank Word template, and even that didn’t get distributed. Eventually I raised a Microsoft support case to help resolve the issue.

As the content type used managed metadata columns and I’d made a minor change to those, I tested with content types created using the same columns but a different template file and one using no managed metadata columns, but with what appeared to be the problematic template file uploaded. Only the example with the problematic template file was affected, but in the same way that we’d seen with the original content type, it didn’t matter what template file we uploaded afterwards, the content type and revised template were not distributed. The template we were using was obviously the issue, however it seemed to break distribution of any content type it was uploaded to from then on.

SharePoint content type templates are held in a folder structure in the root of site collections as follows:

_cts/<content type name>/<template file name>

This is true for both the Content Type Hub where the content types are distributed from, and the destination site collections.

Examining this location in the Content Type Hub (initially using PowerShell, but also using the SharePoint Client Browser), showed the following:

SPCB exploration of cts folder

As can be seen, all of the template files that have been uploaded to the content type were still present! Uploading a new template file does not appear therefore to delete the previous file that was associated with the content type. If one of the uploaded files causes issues distributing the content type, even though it may not be associated with the content type anymore, it continues to cause issues simply by being present in the folder for the content type. For example the following PowerShell retrieves the template filename and URL associated with the content type:

Get-PnPContentType -Identity “Black Marble Presentation” | select DocumentTemplate,DocumentTemplateUrl

In our case, this demonstrated that the template that was causing the issue was not associated with the content type, except by its existence in the folder for the content type in _cts.

The following PowerShell could therefore be used to remove the extraneous template files from the content type folder in the Content Type Hub site collection:

Remove-PnPFile –SiteRelativeUrl “_cts/Black Marble Presentation/<template file name>”

Using the above PowerShell I removed all of the unused template files and then republished the content type with a simple blank Word template initially to test whether the content type was distributed successfully. Once that was shown to be successful I uploaded a revised PowerPoint template file and republished the content type. The revised template was also successfully distributed.

Hiding a Default SharePoint 2010 Content Type Field

Extending some of the default content types available in SharePoint 2010 can result in unwanted fields being shown. An example is extending the ‘Event’ default content type, which has three fields attached which you don’t seem to be able to edit:

Unwanted event fields

In particular, many users would like to remove the Workspace field from calendar entries:

Workspace field

Some users resort to editing the new/edit/view forms to remove the fields that are not wanted, however there is an easier way!

Using the following PowerShell, an unwanted field can be hidden so that it does not appear in the new/edit/view forms:

1 # Get a reference to the web we are using 2 $web = Get-SPWeb 3 4 # Get a reference to the list to which the content type is attached 5 $list = $web.Lists["Holiday Calendar"] 6 7 # Return a list of the fields 8 $fields = $list.fields 9 10 # Select the field we wish to hide 11 $field = $fields | where {$_.internalname -eq "WorkspaceLink"} 12 13 # Show the current 'hidden' status of the field 14 $field.Hidden 15 16 # Set the field to hidden (note that 'CanToggleHidden' must be true to allow this) 17 $field.Hidden = $true 18 19 # Update the field 20 $field.Update()

Creating a new holiday event on the calendar, the field allowing a user to create a workspace is now hidden:

New item form without workspace field

Creating Custom Content Types for SharePoint using Visual Studio (or Notepad) and a few other tools…

There are a number of ways of generating Custom Content Types for SharePoint, some more difficult than others.  One of the easiest ways is to create your own using the SharePoint GUI interface via a web browser, however while a nice ‘point and click’ approach, there is no easy way to extract the resultant custom columns and content types for use on another farm.

At the other end of the spectrum, you can hand code the required XML from scratch and generate the features for installation.  This has the advantage that you can re-use the features you generate, but the fairly obvious disadvantage of having to hand-craft XML for use in the features.

There are also a couple of ‘middle of the road’ approaches, one of which I’m going to comment upon, the other of which is what I am going to briefly discuss here.

The first ‘middle of the road’ approach uses the Codeplex SharePoint 2007 Content Type Viewer, details of the use of which can be found at – I do however have a problem with the approach outlined and I’ll explain why:

The Content Types Viewer is a very useful utility that allows you to extract information about content types from a running instance of SharePoint, even those created via the GUI.  The utility provides you with the Fields (columns), the FieldRefs (for specifying in the content type) and the schema for the content type.

Using it in the way described in the above link, the user would copy the Fields data from the Content Types Viewer and generate a feature to install these fields, then create a content type feature containing the information from the FieldsRefs.

The problem I have with this approach is that none of the information from the schema is used within the content type.  I’ll give and example as to why this is bad:

  • Create a custom content type; it doesn’t matter what columns this contains as long as it contains at least one column that is a choice.  Fill in a number of choices for this column.
  • Create a list associated with your custom content type.
  • Extract the fields and content type using the Content Types Viewer as instructed.
  • Copy the fields and content type features to another farm, install and activate them.
  • Recreate your list using the GUI on your new farm and associate it with your content type.
  • Try to create a new entry in the list.
  • You should see that the choice column(s) you contain no data!

The reason this happens is that the choice information you supplied for your custom content type is contained within the schema for that content type.

To rectify the situation, do the following:

  • Save the list on your original farm as a template (.stp).
  • Copy this template to your new farm and upload it into the list template gallery.
  • Create a new instance of your list from the template.
  • Try to create a new entry in the list and your content type magically now contains the choice data you input on the original farm.

This happens because the schema information is contained within the list template file created on the original farm.  You can test this hypothesis by extracting the manifest.xml from the .stp file you created and looking at it – you should see your choices listed within <CHOICE></CHOICE> XML fields.

While this works quite happily if you only ever want to transplant your custom content type/list combination to another farm, however if anyone creates a list from scratch and associates it with the custom content type on the new farm the list will not be able to function properly.

A better approach is to use the Content Types Viewer, but also include the required information from the schema.  While this involves a little more than ‘cut and paste’ from the Content Types Viewer, it does at least provide a complete content type for transplant to another farm.

Most of the information from the schema should be transplanted into the Fields feature, with the content type feature remaining the same.  A number of fields from the schema should not be transplanted as these cause errors when attempting to install/activate the feature.  These include:

  • Version
  • Customization
  • Aggregation

A few notes:

  • Generally you should use SourceID= in your fields feature.
  • There may be problems associated with referencing other fields for (for example) a calculation field as these typically utilise a GUID to identify the column you wish to extract data from.  If you are referencing columns within the same content type, you can simply use the column name and dispense with the GUID.  If you wish to access information from another list you have a problem as the GUID for the list will be generated dynamically when the list is created.  If you wish to do this you need to create the lists you wish to reference first and extract the list IDs for use in your feature.  An alternative (in particular if you wish to wrap your features up into a SharePoint Solution) is to write a feature receiver to dynamically add the appropriate columns with the correct GUIDs to your feature at activation.

I aim to discuss creating field and content type feature creating in more detail in a future post.