Content Type Hub - Publishing and Subscribing to Content Types Programmatically (C# Code)

Below is a simple code snippet that you can wrap in a site scoped feature to publish and subscribe to content types from a content type hub.

As a precaution, please be careful to use this code snippet in production unless you have thoroughly tested it.

Why do we need it?

This is very useful when you are provisioning a site using a web template. This code, wrapped in a site scoped feature will push the published content types from the hub to the new site. You don’t have to wait and guess when the content types will be available in the newly provisioned site.

 public override void FeatureActivated(SPFeatureReceiverProperties properties)
 {
     SPWeb spWeb = properties.Feature.Parent as SPWeb;
     SPSite spSite = spWeb.Site;
  
     string strCTHubUrl = properties.Feature.Properties["CTHubUrl"].Value;            
  
     using (SPSite siteCtHub = new SPSite(strCTHubUrl))
     {
         using (SPWeb webCtHub = siteCtHub.RootWeb)
         {
             if (ContentTypePublisher.IsContentTypeSharingEnabled(siteCtHub))
             {
                 ContentTypePublisher ctPublisher = new ContentTypePublisher(siteCtHub);
                         
                 IEnumerable<SPContentType> spContentTypes = 
                     webCtHub.AvailableContentTypes
                     .Cast<SPContentType>().Where(ct => ct.Group == "MyGroup");
  
                 foreach (SPContentType spContentType in spContentTypes)
                 {                            
                     ctPublisher.Publish(spContentType);
                     Thread.Sleep(100);
                 }
             }
         }
     }
  
     SPWebApplication spWebApp = spSite.WebApplication;
     
     SPService saMMS = spWebApp.Farm.Services.Cast<SPService>()
         .FirstOrDefault(s => s.TypeName == "Managed Metadata Web Service");
     
     SPJobDefinition ctHubTimerJob = null;
  
     //Run the Content Type Hub Job
     //This timer job is associated with the MMS service application    
     ctHubTimerJob = saMMS.JobDefinitions.Cast<SPJobDefinition>()
         .FirstOrDefault(jd => jd.Title == "Content Type Hub");
     if (ctHubTimerJob == null)
     {
         saMMS = spWebApp.Farm.Services.Cast<SPService>()
             .FirstOrDefault(s => s.TypeName == 
                 "Microsoft SharePoint Foundation Timer");
  
         ctHubTimerJob = saMMS.JobDefinitions.Cast<SPJobDefinition>()
             .FirstOrDefault(jd => jd.Title == 
                 "Content Type Hub");
     }
  
     DateTime startTime = DateTime.Now.ToUniversalTime();
     ctHubTimerJob.RunNow();
  
     while ((from SPJobHistory j in saMMS.JobHistoryEntries 
             where j.JobDefinitionId == 
                 ctHubTimerJob.Id && j.StartTime > 
                 startTime select j).Any() == false)
     {   
         Thread.Sleep(100);
     }
  
     //Run the Content Type Subscriber Job
     //This timer job is associated with the subscriber's web application
     SPJobDefinition ctHubSubTimerJob = spWebApp.JobDefinitions.Cast<SPJobDefinition>()
         .FirstOrDefault(jd => jd.Title == "Content Type Subscriber");
     startTime = new DateTime();
     startTime = DateTime.Now.ToUniversalTime();
     ctHubSubTimerJob.RunNow();
     
     while ((from SPJobHistory j in spWebApp.JobHistoryEntries 
             where j.JobDefinitionId == 
                 ctHubSubTimerJob.Id && j.StartTime > 
                 startTime select j).Any() == false)
     {                
         Thread.Sleep(100);
     }            
 }

The code performs the following:

  1. Publishes the content types from a content type hub site

  2. The feature property CTHubUrl holds the content type hub site url

  3. Only the content types from ‘MyGroup’ are published

  4. The code then gets a reference of the MMS service application in the Farm and executes the ‘Content Type Hub’ job

    • This timer job is responsible to publish/re-publish/un-publish the content types from the content type hub
  5. Sometimes, I have noticed the ‘Content Type Hub’ job is associated with the ‘Microsoft SharePoint Foundation Timer Job’ – so the code checks for the same

  6. The code then gets the ‘Content Type Subscriber’ job associated with the web application and executes it

    • This timer job (scoped to that web application) is responsible for subscribing to the published content types from the hub
  7. In each case, the code waits for the timer jobs to complete

This code can now be used in your web template onet.xml and activated before all of your lists, libraries are created using the referenced subscribed content types.

image

As a precaution, please be careful to use this code snippet in production unless you have thoroughly tested it. Also don’t forget to handle the exceptions. This code snippet does not handle any exceptions that may arise due to the timer job or any other issues.