I recently needed to make several web.config changes to our production SharePoint 2010 web farm. Making all of these modifications manually would have been tedious and would have left a lot of room for error. After doing some research to find a better way, I discovered the SPWebConfigModification class in the Microsoft.SharePoint.Administration namespace.

This is basically  a collection of changes to be made to web.config files that can be stored and then applied to all web front-end servers in a farm. This class is available with SharePoint 2010 and 2013. Unfortunately, the class is poorly documented so I had some trouble figuring out how to use it. You could write a console application to use the SPWebConfigModification class or you could use a feature receiver, but I found that the easiest approach was to just use it with PowerShell. After some trial and error, I came up with the following four PowerShell scripts that can be reused to read, add, remove, and completely clear the SPWebConfigModifications on the server.

The changes can be stored at the web service level, or at the web application level. If you save your changes at the web service level, then changes will be propagated to ALL web application web.config files running on the farm. This could cause serious problems with other web applications on the farm that did not need the modifications. Saving your changes at the web application level will only affect the web.config files for a particular web application.

ClearWebConfigModifications.ps1

First, use the following script to clean out any existing web.config modifications that are currently in the web application. You should be very cautious when using this script because it will delete ALL of the modifications that are currently stored. This would affect any modifications that other developers have added to the system, or any modifications that were added when installing third-party software on the server. Use the ReadWebConfigModifications.ps1 script in the next step and analyze the output before proceeding with this if you are unsure.

Param
(
   $webUrl
)
Add-PsSnapin Microsoft.SharePoint.PowerShell

$site = New-Object Microsoft.SharePoint.SPSite($webUrl)
$webApp = $site.WebApplication;
$webApp.WebConfigModifications.Clear()
$webApp.Update()

Write-Host "Finished clearing configurations."

Remove-PsSnapin Microsoft.SharePoint.PowerShell

The script executes and shows me this in the console:

ReadWebConfigModifications.ps1

Now we can take a look at how to view our stored modifications. This script is used for viewing all modifications that currently exist in both the web service and web application.

Param
(
   $webUrl
)
Add-PsSnapin Microsoft.SharePoint.PowerShell

Write-Host "###############################################"
Write-Host "WebConfigModifications for Service"
Write-Host "###############################################"

$site = New-Object Microsoft.SharePoint.SPSite($webUrl)
$webApp = $site.WebApplication;
$method = [Microsoft.Sharepoint.Administration.SPServiceCollection].GetMethod("GetValue", [Type]::EmptyTypes)
$closedMethod = $method.MakeGenericMethod([Microsoft.SharePoint.Administration.SPWebService])
$webService = $closedMethod.Invoke($webApp.Farm.Services, [Type]::EmptyTypes)
$webService.WebConfigModifications

Write-Host "###############################################"
Write-Host "WebConfigModifications for Web Application"
Write-Host "###############################################"

$webApp.WebConfigModifications

Remove-PsSnapin Microsoft.SharePoint.PowerShell

Since I have already cleared the modifications, I see this when I execute the script above:

Now I have a clean slate to demonstrate how to add a modification.

AddWebConfigModifications.ps1

One of the modifications that I needed to add was for MSChart. I will use that as an example. In the script you will see that for each SPWebConfigModification I am setting a Path, Name, and Value property. The Path property is a path to the node in the web.config file that you would like to add your modification to. The Name property gives the modification a unique name when it is stored. The following convention must be used to ensure that the Name property is unique and that it will not be duplicated when it is applied to the web.config:

$configModSystemWeb.Name = "add[@path='UNIQUE NAME HERE']"

And finally, the Value property which contains the actual XML that you want to inject into the web.config file.  You then use the Add method on SPWebConfigModifiactions to add your modification to the collection. Calling Update on the web application will save the modification to the system, and then Parent.ApplyWebConfigModifiations will actually do the work of applying the saved modification to all of the web.config files in the web application.

Param
(
   $webUrl
)
Add-PsSnapin Microsoft.SharePoint.PowerShell

$configModSystemWeb = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$configModSystemWeb.Path = "/configuration/system.web/httpHandlers"
$configModSystemWeb.Name = "add[@path='ChartImg.axd']"
$configModSystemWeb.Value = "<add path='ChartImg.axd' verb='GET,HEAD' type='System.Web.UI.DataVisualization.Charting.ChartHttpHandler,

System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' validate='false' />"

$configModSystemWebServer = New-Object Microsoft.SharePoint.Administration.SPWebConfigModification
$configModSystemWebServer.Path = "/configuration/system.webServer/handlers"
$configModSystemWebServer.Name = "add[@name='ChartImageHandler']"
$configModSystemWebServer.Value = "<add name='ChartImageHandler' preCondition='integratedMode' verb='GET,HEAD,POST' path='ChartImg.axd'

type='System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=3.5.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35' />"

$webApp = Get-SPWebApplication
$webUrl $webApp.WebConfigModifications.Add($configModSystemWeb)
$webApp.WebConfigModifications.Add($configModSystemWebServer)
$webApp.Update()
$webApp.Parent.ApplyWebConfigModifications()

Write-Host "Finished Updating web.config."

Remove-PsSnapin Microsoft.SharePoint.PowerShell

After executing the above script, I see this:

If I then run my ReadWebConfigModifications.ps1 script again, I will see that the values have been added to my web application:

And if I look at the web.config file on the server, I can see that the modifications were applied:

RemoveWebConfigModifications.ps1

You may want to remove a single modification instead of clearing out the entire collection. Here is a script that will remove only our first entry:

Param
(
   $webUrl
)
Add-PsSnapin Microsoft.SharePoint.PowerShell

$site = New-Object Microsoft.SharePoint.SPSite($webUrl)
$webApp = $site.WebApplication;

# remove chartingWeb config
Write-Host "Removing chartingWeb modification..."
$config = $webApp.WebConfigModifications | Where-Object {$_.Name -eq "add[@path='ChartImg.axd']"}
$webApp.WebConfigModifications.Remove($config)

#update
Write-Host "Updating WebConfigModifications..."
$webApp.Parent.ApplyWebConfigModifications()
$webApp.Update()

Write-Host "Finished removing configurations."

Remove-PsSnapin Microsoft.SharePoint.PowerShell

Here is what I see when I run this script:

If I then run the ReadWebConfigModifications.ps1 script again, I will see that one of the entries has been removed, and that the other is still there:

There are several benefits to using the SPWebConfigModification class over making manual changes to web.config files:

  • Applies web.config changes across all front-end servers in a farm.
  • Ensures that all changes are made exactly the same on all servers.
  • Saves time!