SharePoint 4 Developers

Additional reference guide in .NET / SharePoint Development

SharePoint 2010 Content Type Hub

In this article we will check out a new feature in SharePoint Server 2010 called Content Type Hub, which allows the Content Types centralisation and sharing through the Metadata Service Application. You will understand how it works, how to configure it, how to publish and consume Content Types and some troubleshooting.

Hi folks,

In this article we will check out a new feature in SharePoint Server 2010 called Content Type Hub, which allows the centralisation and sharing of Content Types through the Metadata Service Application. You will understand how it works, how to configure it, how to publish and consume Content Types and also some troubleshooting.

How it works

Widely discussed when using MOSS 2007, the Content Type Sharing was always problematic, because once the Content Types are created in a single Site Collection, they cannot be shared among other Site Collections (there is no OOTB resource for that).

This new feature is available through the Metadata Services Application, which maps the Site Collection in which the Content Types are shared, working like a Hub.

The Figure 1 below displays how a Content Type Hub works:

 MSA
Figure 1 – The operation of a Content Type Hub (Publisher x Subscribers)

The concept of its operation is very simple, basically the Content Type Hub publishes the Content Types and through the Metadata Service Application they are replicated to the Subscribers. These subscribers can be Site Collections that are in different Web Applications even in different Farms (if you wish it).

Content Types Synchronism is done by 2 Timer Jobs that are executed in the background. They are:

  • Content Type Hub – Responsible for managing the Content Types to be published.
  • Content Type Subscriber – Responsible for publishing the Content Types from the Hub to the Content Type Gallery of the Site Collection.

Configuration

Site Collection (Content Type Hub)

A Site Collection needs to be created firstly to serve as the Content Type Hub, in order to do that go to the Central Administration > Application Management > Create Site Collections and create a new Site Collection, according the Figure 2:

 sitecol
Figure 2 – Site Collection Creation

Shortly after that, enable the Feature Content Type Syndication Hub for the Site Collection in the Site Actions > Site Settings > Site collection features, according the Figure 3:

 feature1
Figure 3 – Feature Activation - Content Type Syndication Hub

Note: At the moment this Feature is activated the Site Collection is provisioned as the Content Type Hub.

Metadata Service Application

The Metadata Application Service is a service for sharing metadata, whose main feature is the storage of keywords and term sets (which is not discussed in this paper) and as optional feature to serve as a Hub for Content Types.

In the Farm is possible to have zero or more Metadata Service Applications and this criterion depends entirely on the Design of your solution. In this approach we need only one running service application whose connection will consume only one Content Type Hub. In order to consume more than one Content Type Hub, you need to create another service application for that. This is applicable in case you want to create different scopes for Content Types, e.g. the separation of Content Type Hubs for consumption in an Intranet Web Site and the other one in an Internet Web Site.

Here we are addressing only the planning of the Metadata Application Service as a Hub for Content Types, but if you're interested in exploring more about this service application, see the references in this article.

The Metadata Service Application can be created through Central Administration > Application Management > Manage Service Applications > New > Managed Metadata Service. The Figures 4 and 5 display the necessary data for that:

 metadata3
Figure 4 – Creating a new Metadata Service Application (1/2)

 metadata4
Figure 5 – Creating a new Metadata Service Application (2/2)

Note: An important point to be commented is that once the URL Configuration for the Content Type Hub is set, this cannot be changed by the user interface. If you want to change it after the Service Application is created, use this approach for updating the Metadata Service Application.

As we will not use the Metadata Service Application for storing keywords and term sets, disable the default storage location of this service application in Central Administration > Application Management > Manage Service Applications by selecting the Managed Metadata Service Connection and clicking Properties, according the Figure 6:

 metadataconn
Figure 6 – Settings of the Metadata Service Connection (1/2)

Shortly after that, uncheck the checkboxes according the Figure 7:

metadataconn2
Figure 7 – Settings of the Metadata Service Connection (2/2)

OBS: Only one default storage location for keywords and term sets is allowed in a Web Application, thus let these options available until you decide to use them.

Publishing

The Site Columns and Content Types referenced in the posts Creating Site Columns Programmatically via XML and Creating Content Types Programmatically via XML are going to be used in the Hub, because they will serve us as examples of Content Types to be published.

Note: Just deploy the Site Columns using the script provided. Use another approach for deploying the Content Types, according to this post SharePoint Lesson Series – Lesson 2 – Content Types – Part I.

Once these objects are created, start publishing the Content Types. This task can be done manually or programmatically. I'll show you both.

It is worth remembering that, only for purposes of understanding, Content Type Syndication is the definition to the way that Content Types are organized and shared between Lists and Libraries, which is precisely what we are doing with their publishing using the Content Type Hub.

Manual

In this type of publishing go to Site Actions > Site Settings > Site Content Types and for each Content Type created, under the Settings go to Manage publishing for this content type as shown in the Figure 8 below:

publishing
Figure 8 – Manual Publishing of Content Types (1/2)

Shortly after that, one of the options for publishing is available, according the Figure 9:

publishing2  
Figure 9 – Manual Publishing of Content Types (2/2)

Note: Because we are publishing it for the first time, only the Publish option is available. If you have already published the Content Type, the other two options are available and the current disabled.

Just for clarification, I am commenting on the publishing options:

  • Publish – The Content Type is delivered for being consumed in other Site Collections that reference it.
  • Unpublish – The Content Type is retracted. Its copy remains in the other Site Collections, however its status changes to be no longer Read-Only.
  • Republish – Redo the Content Type Publishing. It should be applied in cases where there was some change in it.

Coding

If you prefer to automate the publishing process (especially if you have multiple Content Types), use the code below for this task.

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using CommonLibrary;
  7. using Microsoft.SharePoint;
  8. using Microsoft.SharePoint.Taxonomy;
  9. using Microsoft.SharePoint.Taxonomy.ContentTypeSync;
  10. using System.Configuration;
  11.  
  12. namespace PublishingContentTypes
  13. {
  14.     public class Program
  15.     {
  16.         public static void Main()
  17.         {
  18.             try
  19.             {
  20.                 string url = ConfigurationManager.AppSettings["Url"].ToString();
  21.                 bool publish = bool.Parse(ConfigurationManager.AppSettings["Publish"].ToString());
  22.  
  23.                 using (SPSite site = new SPSite(url))
  24.                 {
  25.                     using (SPWeb web = site.RootWeb)
  26.                     {
  27.                         string contentTypeXml = Path.GetFullPath("ContentTypes.xml");
  28.  
  29.                         List<string> list = XMLHelper.ReadXML(contentTypeXml);
  30.  
  31.                         foreach (string item in list)
  32.                         {
  33.                             SPContentType ctype = web.ContentTypes[item];
  34.                             if (ctype != null)
  35.                             {
  36.                                 if (publish)
  37.                                 {
  38.                                     // Publishing
  39.                                     ContentTypeHelper.ContentTypePublish(site, ctype);
  40.                                 }
  41.                                 else
  42.                                 {
  43.                                     // Unpublishing
  44.                                     ContentTypeHelper.ContentTypeUnPublish(site, ctype);
  45.                                 }
  46.                             }
  47.                         }
  48.                     }
  49.                 }
  50.             }
  51.             catch (Exception ex)
  52.             {
  53.                 Console.WriteLine(ex.ToString());
  54.             }
  55.         }
  56.     }
  57. }

Note: Be aware of the utilisation of the namespace Microsoft.SharePoint.Taxonomy, which refers to the assembly Microsoft.SharePoint.Taxonomy.dll, which is only available in SharePoint Server 2010 (directory 14\ISAPI).

I have also created some libraries to facilitate the publishing, as you can see it in the solution below:

 script
Figure 10 – Content Types Publishing Solution

The code below refers to the class ContentTypeHelper.cs and shows the details for publishing and unpublishing Content Types:

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Microsoft.SharePoint;
  6. using Microsoft.SharePoint.Taxonomy;
  7. using Microsoft.SharePoint.Taxonomy.ContentTypeSync;
  8.  
  9. namespace CommonLibrary
  10. {
  11.     public static class ContentTypeHelper
  12.     {
  13.         public static void ContentTypePublish(SPSite hubSite, SPContentType ctype)
  14.         {
  15.             // Check to see whether the site is a valid hub site.
  16.             if (ContentTypePublisher.IsContentTypeSharingEnabled(hubSite))
  17.             {
  18.                 ContentTypePublisher publisher = new ContentTypePublisher(hubSite);
  19.  
  20.                 Console.WriteLine("Publishing the content type: " + ctype.Name);
  21.  
  22.                 // Check to see whether this content type has been published.
  23.                 if (publisher.IsPublished(ctype))
  24.                 {
  25.                     Console.WriteLine(ctype.Name + " is a published content type.");
  26.                 }
  27.  
  28.                 publisher.Publish(ctype);
  29.             }
  30.             else
  31.             {
  32.                 // The provided site is not a valid hub site.
  33.                 Console.WriteLine("This site is not a valid hub site");
  34.             }
  35.         }
  36.  
  37.         public static void ContentTypeUnPublish(SPSite hubSite, SPContentType ctype)
  38.         {
  39.             if (ContentTypePublisher.IsContentTypeSharingEnabled(hubSite))
  40.             {
  41.                 ContentTypePublisher publisher = new ContentTypePublisher(hubSite);
  42.  
  43.                 Console.WriteLine("Unpublishing the content type: " + ctype.Name);
  44.  
  45.                 // Check to see whether this content type has been published.
  46.                 if (!publisher.IsPublished(ctype))
  47.                 {
  48.                     Console.WriteLine(ctype.Name + " is not a published content type.");
  49.                 }
  50.                 else
  51.                 {
  52.                     publisher.Unpublish(ctype);
  53.                 }
  54.             }
  55.             else
  56.             {
  57.                 // The provided site is not a valid hub site.
  58.                 Console.WriteLine("This site is not a valid hub site");
  59.             }
  60.         }
  61.     }
  62. }

Download the solution here.

How to consume Content Types

In order to consume the Content Types of the Content Type Hub, make sure you are referencing the Metadata Service Application that offers the service application. This applies only if you are using another Web Application as Hub, otherwise you're already entitled to use it within your Web Application.

Make sure you have referenced the service application in the Central Administration > Application Management > Configure service application associations. The Figure 11 displays the scenario that I have just commented:

 association
Figure 11 – Configuring the service application association

Note: Notice that I have two Web Applications, the 81 serves as Publisher and the 80 as Subscriber. Both use the same service Managed Metadata Service.

In the beginning of this article I quickly commented on the Timer Jobs that are responsible for the Content Types Synchronism, now just exploring a little more, if you want to trigger them after publishing or unpublishing Content Types for a quick check, go to the Central Administration > Monitoring > Check job status and select the desired job definition according the Figures 12 and 13:

 jobdefinition
Figure 12 – Triggering Timer Jobs (1/2)

 jobdefinition2
Figure 13 – Triggering Timer Jobs (2/2)

Note: By forcing the execution of the Timer Jobs above, always trigger the Content Type Hub (Publisher) first and then the Subscribers. The execution is asynchronous, so despite the status changes quickly after triggering the job, probably it will still be running.

Note that there are two Subscribers consuming the Content Types (port 80 and 81) even though the Hub is on port 81, just because other Site Collections within the same Web Application can take advantage of Content Types.

After the asynchronous execution, you have the option to check at the Site Collection Subscribers whether the Content Types were successfully replicated. One possible way is to access the Content Types via Site Actions> Site Settings> Site content types (Group Galleries) and check whether the Content Type is there, according Figure 14:

 happyend
Figure 14 – Content Types published :)

Another possible way is exemplified in the section “Troubleshooting” below.

Troubleshooting

Nothing is perfect, you will always face problems that appear in the middle of the road. Welcome to the Real World!

In order to check the publishing errors there are two ways, both can be checked at the Publisher or at the Subscriber sides, the first way is available on the Hub Site in Site Actions> Site Settings> Content type service application error log (Site Collection Administration group) according Figure 15 below:

 errorpublisher
Figure 15 – Checking the publishing errors at the Publisher side

The second way is available at the Site Collections Subscribers side in Site Actions > Site Settings > Content Type Publishing (Site Collection Administration group) according Figure 16:

errorsubscriber1
Figure 16 – Checking the publishing errors at the Subscriber side (1/2)

NOTE: The figure above shows a successful outcome, because all the Content Types were published correctly (what should happen in your environment). This figure is only used to display where to find the possible publishing errors.

Another point to be reviewed is regarding the Refresh of all the Content Types published. If you wish to force an update of the Subscriber, which has changed for some reason, leave this option selected. This will overwrite the current Content Types with the version of the Publisher.

Visit the link for the publishing error log, there you can also see the publishing errors (the same as the Publisher) as shown in Figure 17:

 errorsubscriber2
Figure 17 – Checking the publishing errors at the Subscriber side (2/2)

Tip of the day

***UPDATED in 29/08/2011***
Features can be used to deploy content types in the Hub. They are always the best practice. Just be aware that this will create a dependency on them with a FeatureId, and by doing this, when you publish the content types, the same Feature on the Site Collections Subscribers will be required, so you can get the content types published.

Other option is to use a Powershell script or Console Application. In this case, when you publish the content types, there is no need to activate any feature in the Site Collections Subscribers.

I hope it clarifies the options you have when deploying and publishing content types. :)

Conclusion

In the version of SharePoint Server 2010, the Service Metadata Application enables the sharing of Content Types, which promotes the Content Type Syndication in different Site Collections from different Web Applications, and even in different Farms!

Enjoy this feature to create a new Design sharing Content Types!

References:
http://www.wictorwilen.se/Post/Plan-your-SharePoint-2010-Content-Type-Hub-carefully.aspx
http://www.chakkaradeep.com/post/SharePoint-2010-Content-Type-Hubs
http://msdn.microsoft.com/en-us/library/ff394469.aspx
http://technet.microsoft.com/en-us/library/ee424403.aspx
http://technet.microsoft.com/en-us/library/ee519603.aspx


Cheers,

Marcel Medina

Click here to read the same content in Portuguese.

SharePoint 2010 Developer Dashboard

Learn how to enable the Developer Dashboard, how to use the APIs to display its Tracing info and how to display the rendering results of your page graphically.

Hi folks,

When developing solutions, developers have the concern to deliver functional solutions that conform to the requested requirements. Although I always analyse the performance of my applications, most of the business solutions that I have worked performance is not a critical factor.

Depending on the scenario, what if performance is a requirement? How to get diagnostic information from your solutions in SharePoint 2010?

Precisely now there is the Developer Dashboard that brings a dashboard of tracing info.

In this article I will show how to enable the Developer Dashboard, how to use the APIs to display its Tracing info and how to display the rendering results of your page graphically.

Introducing the Developer Dashboard

Like something unknown, first of all I would like to introduce the Developer Dashboard, as we can see it below:

1D806A05AA43783B_453_0[1]
Figure 1 - SharePoint 2010 Dashboard Developer

Note: Note that the dashboard border is green, because neither asserts nor critical events are displayed. I'll talk about the color changes later in this post.

The left side shows the http handler events executed during the page rendering and their execution times, whilst in the right side a mix of comprehensive information and also details of the request can be found, such as the queries sent to database.

Interestingly, the links show the callstack of the message and other details, according to the figure below:

1D806A05AA43783B_453_1[1]
Figure 2 - Details of a database query

Once this is not unknown anymore for you, let's check what matters.

Enabling and disabling the Dashboard Developer

By default the Dashboard Developer is disabled and in order to display it there are three possibilities:

  • .Net code

  • STSADM

  • PowerShell

There are also three display levels of the Dashboard. As described below:

  • "On" - the dashboard will always be displayed;

  • "Off" - disables the dashboard;

  • "OnDemand" - adds an icon to the page, which allows the visualization of the dashboard only when clicked (toggling between On and Off).

The figure below displays this icon:

1D806A05AA43783B_453_2[1]
Figure 3 - Developer Dashboard Icon

NOTE: It is important to note that when the Dashboard is enabled using OnDemand, only Administrators and Site Collection Owners have access to it. Members and visitors will not see the icon. In this post the Developer Dashboard will be displayed using the display level "OnDemand", which in my point of view is the ideal.

.Net Code

A Feature that enables or disables the dashboard can be created, instead of using scripts for that. This way the activation or deactivation can be done directly through the Site Collection Features page.

Create a project in Visual Studio 2010 of Empty SharePoint Project called DeveloperDashboard. Choose the option of a Farm Solution. Your initial project should look like this:

1D806A05AA43783B_453_3[1]
Figure 4 – DeveloperDashboard Feature (Initial Project)

Add an Event Receiver to the Feature according the figure 5:

1D806A05AA43783B_453_4[1]
Figure 5 – Adding an Event Receiver

The class DeveloperDashboardEventReceiver will be created automatically, with all the methods commented out. Add the following code for the Feature Activation and Deactivation:

Code Snippet
  1. public override void FeatureActivated(SPFeatureReceiverProperties properties)
  2. {
  3.     SPWebService contentService = SPWebService.ContentService;
  4.     contentService.DeveloperDashboardSettings.DisplayLevel = SPDeveloperDashboardLevel.OnDemand;
  5.     contentService.DeveloperDashboardSettings.Provision();
  6. }
  7.  
  8. public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
  9. {
  10.     SPWebService contentService = SPWebService.ContentService;
  11.     contentService.DeveloperDashboardSettings.DisplayLevel = SPDeveloperDashboardLevel.Off;
  12.     contentService.DeveloperDashboardSettings.Unprovision();
  13. }

In the end your project should look like the figure below:

1D806A05AA43783B_453_5[1]
Figure 6 – DeveloperDashboard Feature (Final Project)

Compile and deploy the project directly from the Visual Studio 2010 in development environments. For production environments deploy it via STSADM according the figure below:

1D806A05AA43783B_453_6[1]
Figure 7 - Deploy of the feature on Production

In the end this feature must be enabled as the following figure:

1D806A05AA43783B_453_7[1]
Figure 8 - Deploy of the Feature "Developer Dashboard"

Download the solution here.

STSADM

Open the Command console and enter the following cmdlet to enable the Developer Dashboard:

stsadm –o setproperty –pn developer-dashboard –pv OnDemand

To disable it:

stsadm –o setproperty –pn developer-dashboard –pv Off

NOTE: The option-pv is case-sensitive.

Result:

1D806A05AA43783B_453_8[1]
Figure 9 - Execution of commands via STSADM


PowerShell

Another possibility is to use PowerShell for running scripts.

To enable the Developer Dashboard:

$dash = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$settings = $dash.DeveloperDashboardSettings
$settings.DisplayLevel = [Microsoft.SharePoint.Administration.SPDeveloperDashboardLevel]::OnDemand
$settings.Update()

Result:

1D806A05AA43783B_453_9[1]
Figure 10 - Script activation via PowerShell

To disable it:

$dash = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$settings = $dash.DeveloperDashboardSettings
$settings.DisplayLevel = [Microsoft.SharePoint.Administration.SPDeveloperDashboardLevel]::Off
$settings.Update()

Result:

1D806A05AA43783B_453_10[1]
Figure 11 - Script deactivation via PowerShell


Measuring performance and adding messages via Tracing

Once the Developer Dashboard is active, we can proceed with the addition of Tracing messages in SharePoint 2010.

As already said this is an excellent way to measure the performance of code and add custom messages for tracking.

In order to measure the time of the code snippet that we intend to track, the class SPMonitoredScope should be used. This information will be available on the left side of the Dashboard.

In order to add log messages, warnings or assert messages, the class SPCriticalTraceCounter should be used. This information will be available on the right side of the dashboard, and a link will be available to visualize the message details.

NOTE: The callstack, which is in the message details, can add a few Kb on the page. Thus track the growth of the amount of custom messages that you have, they will increase the size (Kb) of your page if the Developer Dashboard is enabled.

Add a new project of Visual Web Part called Tracing. The solution should resemble the figure below:

1D806A05AA43783B_453_11[1]
Figure 12 - Web Part Tracing Project

Add the code below in the file TracingWebPartUserControl.ascx.cs:

Code Snippet
  1. using System;
  2. using System.Web.UI;
  3. using System.Web.UI.WebControls;
  4. using System.Web.UI.WebControls.WebParts;
  5. using Microsoft.SharePoint.Utilities;
  6.  
  7. namespace Tracing.TracingWebPart
  8. {
  9.     public partial class TracingWebPartUserControl : UserControl
  10.     {
  11.         protected void Page_Load(object sender, EventArgs e)
  12.         {
  13.             // Using class for tracking the execution time
  14.             using (SPMonitoredScope sc = new SPMonitoredScope("LoadMeter"))
  15.             {
  16.                 for (uint i = 0; i < 10; i++)
  17.                 {
  18.                     // Adding custom messages
  19.                     SPCriticalTraceCounter.AddDataToScope(i, "Loop For", 15, string.Format("Mensagem monitorada - {0}", i.ToString()));
  20.                 }
  21.             }
  22.         }
  23.     }
  24. }

Class TracingWebPartUserControl

This code contains two classes SPMonitoredScope and SPCriticalTraceCounter as already commented. It is important to know that the TraceLevel (3rd parameter of the method AddDataToScope) can be:

  • 1 – Critical
  • 4 - Exception (Watson)
  • 6 – Assert
  • 8 – Warning
  • 10 – Unexpected
  • 15 - Monitorable

Perform the addition of the Web Part (1), save it (2) and then visualize the Developer Dashboard (3) as shown below:

1D806A05AA43783B_453_12[1]
Figure 13 - Adding Web Part Tracing

Check out the Developer Dashboard, its border color is no longer green color as displayed in Figure 1. Differently it is in red color, which shows that asserts and critical events occurred (in this case the messages created):

1D806A05AA43783B_453_13[1]
Figure 14 - Time Scope and custom messages added

Click over one of the messages and note that the message details and callstack can be seen:

1D806A05AA43783B_453_14[1]
Figure 15 - custom message displayed in details

Download the solution here.

Developer Dashboard Visualizer

We can improve the Dashboard with a graphic display called Developer Dashboard Visualizer, which was created by Jaap Vossers and consists of a UserControl that makes use of JQuery to view the axis Events x Execution time (left side of the Developer Dashboard).

This project is available on Codeplex: http://devdashvis.codeplex.com/

Download the wsp package and install it using the STSADM, as shown below:

1D806A05AA43783B_453_15[1]
Figure 16 - Enabling the Developer Dashboard Visualizer

The http handler events are displayed immediately above the dashboard:

1D806A05AA43783B_453_16[1]
Figure 17 - Graphical View

In this article we checked how to enable the SharePoint 2010 Developer Dashboard. We have checked that diagnostic information and tracing messages are output on the page to the browser that made the request. Such information may help to clarify errors or undesired results during the processing of your solution in SharePoint 2010.

I hope these tips are helpful.

References:
http://blogs.msdn.com/pandrew/archive/2010/03/26/sharepoint-2010-developer-dashboard-for-debugging-code.aspx
http://weblogs.asp.net/jcortez/archive/2010/03/16/developer-dashboard-in-sharepoint-2010.aspx
http://devdashvis.codeplex.com/

Cheers,

Marcel Medina

Click here to read the same content in Portuguese.