Hi, I'm Martin Kearn ...
I am a Technical Evangelist for Microsoft, UK. I blog about everything relating to developing apps and websites on the Microsoft stack. This includes ASP.net, Azure, Windows Apps and Office Apps. I used to do a load of stuff with SharePoint so many of my older post are SharePoint related.
Follow me on Twitter @MartinKearn
Ok, I'll admit that this is not the most snappily-named blog title; however it will address a specific problem that I've hit a few times at different customers; which is how to make automated modifications to sites after they have been deployed and used.
The scenario I am hoping to address here is when you build a site structure based on standard site templates but one day a requirement arises to change all of the sites for some reason (very common given the 'organic' nature of SharePoint). There are lots of reasons why you might need to do this; here are just some of the common ones:
- Changing master page, CSS or theme on specific sites or part of any overall structure
- Associating content types or site columns with all libraries
- Adding specific security settings to a site
The list goes on, this basically applies to anything that you could do through Site Settings but want to automate.
The problem is that the sites are already out there being used and therefore you cannot change the template or definition that the site is based on (which you'd do if you knew about the requirement beforehand). The other approach is manually configuring the sites via the UI, but this is just not realistic in large structures.
Throughout this article I'll use the scenario of adding a content type (let's say the standard 'Dublin Core Columns' content type) to every document library in the site structure, but this could be applied to a plethora of different scenarios .... anywhere where you need to execute some one-off code to do something to an existing site or range of sites.
To address this requirement, we build what is known as a 'Code Call-out Feature', this is basically a feature that simply executes some code when it is activated. Once written and installed, you can activate the feature by using STSADM.exe command line utility. You can use a batch file to repeat this command throughout your entire site structure if desired (more on this later).
Before you get worried about the fact that we are talking about code here, don't worry – it is really very simple, even if you are not a 'developer'. The following steps have been written for someone that has only very basic experience with Visual Studio, so if you are a more established developer some of this may be a little obvious.
Step 1 – Setup your Visual Studio project
The first step is to setup your Visual Studio project for the .net assembly that will get called when your feature is activated. Simply follow these steps:
a. Open Visual Studio and create a C# 'Class Library' project called 'CTAssociation'
b. In Solution Explorer, right-click on your project and click 'Add Reference', go to the 'Browse' tab and choose Microsoft.SharePoint.dll (normally located in C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI\Microsoft.SharePoint.dll)
c. Go to the project properties (Projects > CTAssociation properties) and do the following:
- On the Application tab set the Assembly name to 'CTAssociation.DublinCore' and the namespace to 'CTAssociation'
- On the Signing tab, check 'Sign the assembly' and create a new Strong Name Key file (choose 'new' from the drop-down)
d. Open 'Class1.cs' and change it so that it looks like this (I've highlighted the things that you need to add or change):
e. Save and Build your project (ensure you have no errors)
2 – Add your assembly to the GAC
Providing your project built OK, you should now have a new DLL called CTAssociation.DublinCore.dll located in My Documents\Visual Studio 2005\Projects\CTAssociation\CTAssociation\Bin\Debug. We need to add this to the Global Assembly Cache (GAC). To do this follow these steps:
Now that the assembly has been added to the GAC, you will be able to get the Public key Token which will be required later one, to do this follow these steps:
3 – Setup your Feature
Now that your assembly has been added to the GAC, we need to build the feature that calls it when activated. The 'Code Callout feature' is one of the simplest ones to create, follow these steps
All features have to have a unique identifier called a GUID. The easiest way to create a GUID is to use a tool that comes with Visual Studio called GUIDgen.exe. Follow these steps:
Now that you have your GUID and Public key Token, you can create the actual feature. To do this follow these steps:
Title="Content Type Association - Dublin Core Columns"
ReceiverAssembly="CTAssociation.DublinCore, Version=188.8.131.52, Culture=neutral, PublicKeyToken=d43c4c8ff8fcf2b6"
4 – Install your Feature
Installing your feature could not be simpler. There is an STSADM.exe parameters called 'InstallFeature'. To install the feature follow these steps:
stsadm.exe -o installfeature -name "CTAssociationDublinCore" –force
Providing all is well your feature should now be installed. Next thing to do is test that is basically works (i.e. throws the "This feature was activated!!" message when activated). To do this follow these steps:
<screen of error>
5 – Writing the code to add a Content Type
At this point you have all the plumbing in place to starting adding functionality to your feature. This is the point where you add the code to make the modification that you require.
It is not in the scope of this article to explain how to do this in detail; the article is more about how to create the feature. However, in our example of adding a new content type to all document libraries, the code would look something like this:
SPWeb oWeb = (SPWeb)properties.Feature.Parent;
SPContentType oCT = oThisWeb.Site.RootWeb.ContentTypes["Dublin Core Columns"];
foreach (SPList oList in oThisWeb.Lists)
//check if the current list is a document library
if (oList.BaseTemplate == SPListTemplateType.DocumentLibrary)
dDocLibCount += 1;
oList.ContentTypesEnabled = true;
//if the above throws an exception, it means the content type is already on this list. This does not matter so catch the exception and carry on
//if there were no document libraries throw an exception
if (dDocLibCount == 0)
throw new Exception("There were no lists of the Document Library type in this Site, therefore no updates were made and the Content Type was not associated with any lists.");
//update the list
In summary, code-callout features are a very powerful capability which allow you to make changes to you existing Sharepoint solutions after they have been deployed and are actively being used.