Monthly Archives: May 2014

SPWebConfigModification and SharePoint 2013

Sometimes it is needed to modify the web.config to change default ASP.NET settings. Within a  SharePoint environment you don’t want to do this manually, because it is error prone and also the changes are not propagated among all web front end servers in a single farm.

Within SharePoint there is a API called SPWebConfigModification which allows you to programmatically modify the web.config using XPath. The changes are automatically applied on the front ends using a built-in timerjob. In SharePoint 2010 it turned out that this API was not always stable. Some weird behavior is sometimes experienced with removing entries programmatically. According to some sounds from the community we can conclude that that has been fixed. Using that article and some others you will be able to create a solution to modify some attributes in the Web.config. Unfortunately there are not much examples and also MSDN documentation lacks some samples with some more complex XPath modifications using SPWebConfigModification class. In this post I want to show a more complex modifications to the web config the web.config instead of a small sample with only modifying an attribute.

Let’s assume that we want to add the following structure to the web.config to increase the execution timeout setting of a specific applicationpage. We want to add this under the node in the web.config file.

<location path="_layouts/15/PathToApplicationPage.aspx ">
    <system.web>
        <httpRuntime executionTimeout="600" />
    </system.web>
</location>

The SPWebConfigModification API provides methods to add/modify/delete sections, child elements and attributes. Unfortunately this API is not very well documented, which makes it hard the to implement this. It uses internally XPath to modify the web.config XML. It uses a Name and Path which needs to be a unique combination to identify the modification. These variables are needed to perform later operations like updating or deleting when you want to programmatically change your settings. Also the owner field is needed so that you identify which application has made the modification. Suggestion here is to use the assembly full name for the owner field, some unique key for the name and the path in XML where the node/section/attribute should be created/modified. The following code shows a sample of a utility class which you can use as basis for doing SPWebConfigModifications in your own full trust solution:

internal abstract class WebConfigUtility
{
	/// <summary>
	/// Holds the owner
	/// </summary>
	private readonly string owner;

	/// <summary>
	/// Gets or sets the sequence
	/// </summary>
	private uint Sequence
	{
		get;
		set;
	}

	protected WebConfigUtility()
	{
		owner = GetType().FullName;
	}

	/// <summary>
	/// Adds a new xml attribute to the web config file.
	/// </summary>
	/// <param name="name">
	/// Name of the attribute.
	/// </param>
	/// parentPath">
	/// The parent of this attribute.
	/// </param>
	/// <param name="value">
	/// The value of the attribute.
	/// </param>
	protected void CreateAttribute(string name, string parentPath, string value)
	{
		var webConfigModification = new SPWebConfigModification(name, parentPath)
		{
			Owner = owner,
			Sequence = Sequence,
			Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute,
			Value = value
		};
		AddConfigModification(webConfigModification);
	} 

	/// <summary>
	/// Adds a new xml node to the web config file.
	/// </summary>
	/// <param name="name">
	/// Name of the node.
	/// </param>
	/// parentPath">
	/// The parent of this node
	/// </param>
	/// <param name="value">
	/// The value of the node.
	/// </param>
	protected void CreateNode(string name, string parentPath, string value)
	{
		var webConfigModification = new SPWebConfigModification(name, parentPath)
		{
			Owner = owner,
			Sequence = Sequence,
			Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode,
			Value = value
		};
		AddConfigModification(webConfigModification);
	}

	/// <summary>
	/// Only use this if you need to add a section that does not have to be removed and may contain child nodes from other solutions.
	/// </summary>
	/// <param name="name">
	/// The name of the section.
	/// </param>
	/// <param name="parentPath">
	/// The parent path in the web.config file.
	/// </param>
	protected void CreateSection(string name, string parentPath)
	{
		var webConfigModification = new SPWebConfigModification(name, parentPath)
		{
			Owner = owner,
			Sequence = Sequence,
			Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection
		};
		AddConfigModification(webConfigModification);
	}

	/// <summary
	/// Adds the config modification.
	/// </summary>
	/// <param name="modification">
	/// The modification to apply.
	/// </param>
	private void AddConfigModification(SPWebConfigModification modification)
	{
		WebConfigModifications.Add(modification);
		Sequence++;
	}

	/// <summary>
	/// Removes the modifications of the webconfig of the current webapplication.
	/// </summary>
	/// <param name="webApplication">
	/// The web application.
	/// </param>
	internal void RemoveInternal(SPWebApplication webApplication)
	{
		if (webApplication == null)
		{
			throw new ArgumentNullException("webApplication");
		} 

		var toRemove = webApplication.WebConfigModifications.Where(modification => modification != null).Where(modification => string.Compare(modification.Owner, owner, true, CultureInfo.CurrentCulture) == 0).ToList(); 

		foreach (var modification in toRemove)
		{
			webApplication.WebConfigModifications.Remove(modification);
		} 

		UpdateWebConfig(webApplication);
	}

	/// <summary>
	/// Updates the webconfig of the current webapplication with the modifications.
	/// </summary>
	/// <param name="webApplication">
	/// The webapplication that needs to be configured.
	/// </param>
	protected void UpdateWebConfig(SPWebApplication webApplication)
	{
		try
		{
			webApplication.Update();
			webApplication.WebService.ApplyWebConfigModifications();
		}
		catch (Exception ex)
		{
                      // Add your exception handling and logging here
		}
	}
}

Let’s consider our first example and the helper class above to create the modifications:

CreateNode("location[@path='_layouts/15/PathToApplicationPage.aspx']", "configuration", "");

In this sample we add a new node. As name we specify a unique name which can be used to identify it later on. The second parameter is a path. This is configuration as we want to store the node under the configuration key. Please choose a different path when you need to create the node on a different location. The last parameter is the actual value. You can then use the UpdateWebConfig method together with a SPWebApplication object to save the changes. Also methods are included for removal which works in a similar way.

SharePoint Migration & Search Part 2: Search Web Parts

In a few series of posts I will discuss changes in SharePoint Search which might affect you when migrating from SharePoint 2010 to 2013. Search is one of the most changed components in SharePoint 2013 and therefore I split the posts up in four parts covering some subjects you need to know before migrating to SharePoint 2013. All parts will be available with the links below when the posts are available:

Part 1: Search Settings
Part 2: Search Web Parts
Part 3: Search Results Sources
Part 4: Search Result Types and Display Templates

In this post I will describe the changes to Search Web Parts in-depth. These Web Parts were changed as part of the new search platform which is available in SharePoint 2013.

First thing you’ll notice when using SharePoint 2013 is the number of search Web Parts available. When you want to add a search Web Part you see that the number of Web Parts has been reduced drastically.SearchWebParts

When you look to this list at the first time it looks like a lot of search functionality is missing in SharePoint 2013. But that’s not right as we will see later. The best way how to show that is on the results page in a OOTB Search Center and let’s see the difference in number Web Parts in edit mode.

Search Results Page SharePoint 2010

The search results page in a search center in SharePoint 2010 contains a lot of Web Parts to display all information.

Let’s compare this to the same page when using a SharePoint 2013 Search Center:

The Search Results Page in SharePoint 2013 contains only a few Web Parts.

The Search Results Page in SharePoint 2013 contains only a few Web Parts.

There is a simple clarification for this enormous reduction of a number of Search Web Parts and that is integration. The new Search Result Web Part is now containing the functionality of a lot of other Web Parts like the Search Paging, Search Statistics, People Search Results, etc. This is a major advantage when maintaining and configuring search Web Parts.

Another major change is the way how the Web Parts are configured. In 2010 and before XSLT was the way to go when changing the search results being displayed. In 2013 this has been removed and you need to use Display Templates. Those Display Templates can be coupled to Result Types. Based on the type of search results you can customize the way search results are displayed. I will cover this more in-depth in part 3 of these series of articles. This implies that you need to change your customized search functionality in your solutions if you’re using it and want to use customized search results.

As probably already noticed Search Scopes are deprecated in SharePoint 2013. Deprecated means that no new scopes can be created and existing scopes are read-only (this is also blocked from API). This also has implications for the Search Web Parts. The new Search Web Parts don’t provide support for Search Scopes but only for result sources. For example, the scopes drop down functionality is no longer part of the Search Box Web Part.

Another thing to mention is the Site Collection Upgrade. When using a standard Search Center without modifications there is nothing to be done. The Site Upgrade handles the transition automatically. In case you are using search Web Parts outside a Search Center the upgrade process does not replace the Web Parts! This will results is some glitches.
First problem you’ll notice is the styling. The old Web Parts do not comply with the 2013 style sheets which results in big buttons and other similar ugly glitches. Make sure you have an upgrade strategy ready for this and mitigate this using custom feature upgrades or manual steps after the Site Upgrade! Replacing the Web Parts can only be done after Site Upgrade. The 2013 Search Web Parts won’t work when in 2010 mode!
Another thing I’ve noticed is that when still using the old Web Parts in 2013 mode, is that the search scopes are not respected anymore. SharePoint uses in 2013 a different way of creating the search URL’s and these are not compatible with the old Web Parts. That results for example that an All Site scope search automatically results in a search on whole SharePoint. Again the only way to resolve this is by replacing the Web Parts. An approach there is to create new 2013 search pages in your solution in a subfolder and using a feature reactivation provision these on new sites and also update the search configuration as mentioned in Part 1 of the series.

To conclude this post I will provide an overview of all Search Web Parts available in 2010 and 2013:

SharePoint 2010 SharePoint 2013
Advanced Search Box Advanced Search Box*
Dual Chinese Search Search Box
Federated Results Search Navigation
People Refinement Panel Search Results
People Search Box Refinement
People Search Core Results
Refinement Panel
Related Queries
Search Action Links
Search Best Bets
Search Box
Search Core Results
Search Paging
Search Statistics
Search Summary
Search Visual Best Bet
Top Federated Results

* The Advanced Search Web Part is missing in the Web Part gallery but it still part of SharePoint. It is still possible to use that Web Part, but you need to export it from a Search Center and import the .webpart file in your site to use it.