Alternative Perspectives for the Discerning SharePoint Developer    

Inspirational Sharecasm

Go Search
Home
  

Using a Web Application Feature to Modify web.config

So, what if you need to make a change to the web.config file for a SharePoint Web Application? If the modification is for adding a SafeControl element or modifying the Code Access Security Setting for a Web Part assembly, you should not be writing code to accomplish this. Instead, you should be updating the web.config file declaratively using SafeControl elements and CodeAccessSecurity elements inside the manifest.xml file within a solution package. However, for any other web.config settings you want to add or modify, you cannot do it declaratively. That's when you have to resort to writing code against the WSS object model.

In this blog post I am going to show an example of how to modify the web.config file to switch back and forth between debug mode and standard user mode. Let me confess I did not figure how to do this on my own. Dan Larson and Tony Bierman were blogging about this back in 2006. Scot Hillier also posted a series of SharePoint Features on CodePlex including a project named the Debug Config Feature which does something very similar to what I am going to show here. I simply took what I learned from them and refactored the code to a more simplified state to facilitate your ability to get up to speed so you can reuse within the projects you are working on.

Let's begin by looking at a simple console application that's been written to make an update the web.config file for a specific Web Application. In this scenario, imagine you want to add a simple entry to the web.config file such as a named key/value pair into the appSetting section that looks like this.

Within your project you must add a reference to the Microsoft.SharePoint.dll assembly so you can program against classes in the Microsoft.SharePoint.Administration namespace such as SPWebService, SPWebApplication and SPWebConfigModification. Here's the basic code required to update the web.config file for a SharePoint Web Application with the new appSetting element.

Keep in mind that a modification such as this doesn't necessarily apply to just one web.config file. For example, imagine you run this code in a Web farm with four front-end Web servers. You'll be required to update four web.config files instead of just one. What if the target Web Application is configured with an Internet zone in addition to the default zone? In this scenario you will be required to update eight web.config files with the current SharePoint farm. The best part of using the WSS object model and an SPWebConfigModification object is that you don't have to worry about how many web.config files are associated with the target Web Application. WSS abstracts those details away and deals with making all the proper updates behind the scenes. Furthermore, you can write the code required to update the web.config file within the event handler for a feature and then you can add that feature to a solution package so it can be deployed in production farms using best practice techniques. That's what we will do next.

Now let's step through a sample Visual Studio project named SharePointDebugger which demonstrates how to put all the pieces together. There is a ZIP archive on our downloads page named SharePointDebugger.zip which contains this project code which you can load into Visual Studio 2005 so that you can follow me along. This Visual Studio project has the standard structure for SharePoint development that we in our training classes. The project has been designed to build the project's components into a solution package and to deploy this solution package on the local machine for testing purposes. If you have a development workstation which is a stand-alone farm running either WSS or MOSS, you should be able to open the SharePointDebugger project in Visual Studio and simply build it to test out the code.

The programming logic which updates the web.config file has been added the FeatureActivated event handler within a feature named SharePointDebugger. Remember the purpose of this code is to modify the web.config file. But you don't want just anyone that happens to have privileges within a site or site collection doing something that could modify the web.config file. Therefore, I scoped this feature at the Web Application level instead of having a feature scope of Site or Site Collection.

In order to activate the feature, a user will be required to possess either farm-level permissions or permissions for the target Web Application. Here's a view of how the feature appears within the user interface of the SharePoint Central Administration Application.

When you click the button to activate the SharePointDebugger feature on a particular Web Application, the FeatureActivated event handler executes. First thing you need to do inside the implementation of this event handler is get a hold of the SPWebApplication object for the current Web Application.

Over the last year I have created several projects that have been required to update the web.config file. Therefore, I found a way to structure my code to make it reusable and more adaptable. Let's start by examining a custom structure named ModificationEntry that I designed to store all the data required to make a single modification entry.

Next, I created a private method named CreateModifcation that accepts an instance of the ModificationEntry structure and returns an initialized SPWebConfigModification object.

With this approach, I can simply declare an array of ModificationEntry instances within each project which makes it easy to add, modify and remove entries that will be used to update the web.config file. For example, here are the modification entries required to switch the standard SharePoint web.config file from standard user mode over to debug mode.

What I like about using this approach is that the code within the FeatureActivated event handler becomes boilerplate and does not change from project to project.

Another important thing to keep in mind is that SharePoint records all these web.config modifications within the configuration database. That makes it possible to roll them back. You can then simply take the same SPWebConfigModification object and remove it from the WebConfigModifications collection of a Web Application to roll back modifications you have made to the web.config file. When you deactivate the SharePointDebugger feature, it returns the web.config file back to its initial state of standard user mode instead of debug mode.

I use the SharePointDebugger feature on a regular basis when I am coding or when I am teaching a training class because it is so much quicker than making manual edits to the web.config file. However, this technique for updating the web.config file has so many other applications such as adding web.config entries for connection strings, for AJAX extensions and for your own custom HttpModules and HttpHandlers that you want to integrate into a SharePoint solution.

Understanding Site Pages versus Application Pages

Some pages in a WSS site, such as a site's home page (default.aspx), support user customization through the browser via Web Parts and through other customization tools such as the SharePoint Designer. Pages that support user customization are known as site pages and they exist within the virtual file system that SharePoint maintains for a specific site. SharePoint technology's support for the customization of site pages provides a great deal of flexibility and gives it many advantages over other platforms such as ASP.NET. However, this customization support also introduces several notable disadvantages with respect to scalability, maintainability and security.

Site pages such as default.aspx and the form pages for lists (e.g. AllItems.aspx, NewForms.aspx) are based on underlying page templates. For example, when a site page is initially provisioned from a page template, it exists in an uncustomized state. The SharePoint runtime uses the page template on the file system of the front end Web server when processing requests. Once a site page is customized with the SharePoint Designer, a customized copy of the .ASPX file is stored in the content database and the association between the site page and its underlying template is broken. This can lead to the following problems.

  • Performance problems (likely unnoticeable except in high-traffic farms)
  • Security problems (pages now render is Safe Mode)
  • Maintainability problem #1 (update to page template doesn't affect customized pages)
  • Maintainability problem #2 (the users can screw things up)

When creating a reusable developer solution for SharePoint sites in which you choose to add site pages, you should generally prefer to create a custom feature which has one or more page templates. If you have never done this before, you can download a sample features named CustomSitePages from the TPG downloads page. This zip file contains a Visual Studio project which shows examples of provision site pages for standard .ASPX pages as well as Web Part pages. It also demonstrates how to provision site pages from page templates using a Module element within a feature.

While the customization made possible by site pages is definitely one of the most attractive aspects of the SharePoint platform, it's not always required or even desired. There are many scenarios in which you want to add pages to a SharePoint site that do not support customization. That's where application pages come in. One of the key characteristics of an application page is that it does not support user customization. Therefore, application pages circumvent many of the concerns that site pages have with respect to performance, security and maintainability.

As a SharePoint developer, you should consider application pages as one of the primary building blocks when you are creating business solutions. If you want to get going developing custom application, you should download the sample named CustomApplicationPages which is also available on our downloads page.

First, it is important that you understand exactly what application pages are and how their processing differs from that of site pages. Let's start with an example of an out-of-the-box application page, the standard Site Settings page named settings.aspx. This application page can be accessed from any site, yet it does not support customization. These types of application pages are deployed as physical files on the file system of the front-end Web server in a directory at the following path:

c:\program files\common files\microsoft shared\web server extensions\12\TEMPLATE\LAYOUTS

Note that the physical \LAYOUTS directory is mapped in the IIS metabase to the virtual _layouts directory. This mapping is setup whenever WSS creates a new Web application from an IIS Web site. By using this mapping scheme along with some additional processing logic, the WSS runtime can make each application page accessible within the context of any site in the farm. For example, assume that there are three different sites in a WSS farm accessible through the following three URLs:

http://Litwareinc.com
http://Litwareinc.com/sites/Partners
http://Intanet.Litwareinc.com/sites/Sales

An application page, such as settings.aspx, can be accessed by adding its relative path within the _layouts directory to the end of a site's URL. For example, you can access the Site Setting page by using any of the following three URLs:

http://Litwareinc.com/_layouts/settings.aspx
http://Litwareinc.com/sites/Partners/_layouts/settings.aspx
http://Intanet.Litwareinc.com/sites/Sales/_layouts/settings.aspx

Because there is only one version of an application page scoped at the farm level, it can be compiled into a single DLL and loaded into memory once for each Web application. You never have to worry about the existence of multiple versions of an application page for different sites. Furthermore, application pages are not subject to attack from users who have permissions to customize site pages. Therefore, WSS does not prohibit them from containing in-line code nor does WSS require ASP.NET controls on application pages to be marked within the SafeControl section of the web.config file.

Maybe you never really thought about application pages before in custom SharePoint development before. You might be wondering whether you should use them or not. Here's one reason you should consider using them. Application pages are used extensively by the WSS and MOSS teams to supply much of the standard functionality for provisioning and administrating sites and the elements inside them such as lists and document libraries.

If you open and inspect the source code for many of the standard WSS and MOSS application such as setting.aspx, you will see that they link to a master page in the _layouts directory named application.master. When you create your own custom application pages, you might want to follow suit and create them to link to the application.master file as well. You can alternatively provide your own custom Master Page for your custom application pages to create a custom layout.

What should you take away from this blog post? As a developer creating custom solutions for WSS and MOSS, you should begin thinking about sites pages versus application pages early in the design phase. For each occasion when your solution needs to add another page to a SharePoint site, you should be asking yourself whether you should implement this page as a site page or an application page. Now let's finish with a summarization of why you might prefer one over the other.

The reasons to create pages as site pages

  • The page must support customization through Web Parts
  • The page must support customization through the SharePoint Designer
  • The page must be added dynamically through code or through feature activation
  • You must add multiple instances of the page to a site

The reasons to create pages as application pages

  • You want to prohibit user customization
  • You want to avoid safe mode processing
  • You want to achieve the best possible performance
Stapling Features to the Global Site Definition 

If you are developing Features for SharePoint 2007, then Feature Stapling is one of those must-have techniques that you should have in your arsenal. The idea is that you can staple a Feature to a configuration defined within a site definition so that the Feature is automatically activated whenever a new site is provisioned from that specific configuration.

You staple a Feature to a configuration within a site definition using a second Feature. The second Feature must provide a FeatureSiteTemplateAssociation element which specifies the identifying GUID of the target feature along with a formatted string used to identify a site definition and a target configuration. For example, you could write the following CAML element to staple a Feature to the WSS site template named Team Site whose formatted string is STS#0.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<FeatureSiteTemplateAssociation
Id="EACA8B4F-B626-4359-8440-62415404D9E8"
TemplateName="STS#0" />
</Elements>

One very powerful aspect of doing this is that you can staple a Feature to the GLOBAL site definition which will then become associated with every configuration from every site definition. This makes it possible to create a feature that is automatically activated whenever any new site is created on a farm-wide basis. At a higher level, this approach provides you with a technique to extend the GLOBAL site definition without touching GLOBAL site definition directory. All you have to do is add a FeatureSiteTemplateAssociation element which looks like this

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<FeatureSiteTemplateAssociation
Id="EACA8B4F-B626-4359-8440-62415404D9E8"
TemplateName="GLOBAL" />
</Elements>

If you have a SharePoint 2007 development and you want to try this out, I have posted a sample project named CommonSiteInit on the downloads page on my Web site. When you expand the files inside CommonSiteInit.zip it will allow you to work with the sample project shown here.

The CommonSiteInit project contains a Feature named CommonSiteInitStapling which staples the CommonSIteInit Feature to the GLOBAL site definition. The named CommonSiteInitStapling Feature produces the effect of automatically activating the CommonSIteInit Feature during the provisioning of a new site. The CommonSIteInit Feature runs some common initialization code inside its Activation event and adds a new menu item to the Site Actions menu. I am sure you will be able to take this starting point and thing up common initialization code and CAML elements that you would want to be part of any new site.

The CommonSiteInitStapling Feature has an activate scope of WebApplication which means it stapling effect can be enabled and disabled on a Web Application by Web Application basis. You can alternatively design stapling Feature at Farm scope so that the Feature stapling effect is all-or-nothing on a Farm wide basis.

What's up with the Blank Site template from WSS?

When I started testing Feature stapling with the GLOBAL site definition, it worked great with one exception. It did not work as expected with new sites created from the WSS site template known as Blank Site. Mike Ammerlaan from the SharePoint product team filled me in on the details of why this is.

The reason for why Blank Site behaves differently came about when the SharePoint team was designing support for their Web Content Management. They support content deployment using paths and jobs where a company can push content from a source site to a destination site to move content from staging to production. In this scheme, the destination site needs to be a blank site that is *truly* a blank site. They saw the need to suppress arbitrary changes made to new blank site from Feature that may be stapled to the GLOBAL site definition. Therefore, the SharePoint team added a flag in CAML for defining a site definition's configuration so that it can opt out of stapling from the GLOBAL site definition. More specifically, the configuration for Blank Site (STS#1) is defined with an attribute named AllowGlobalFeatureAssociations which is set to false. You can see this for yourself in the WSS system file named 12\template\1033\xml\webtemp.xml.

Now you see the reason why Feature stapling to the GLOBAL site definition does not affect the Blank Site template. So, what if you want to staple a Feature every new site including those created from the WSS Blank Site template? The most straight-forward approach is to add a second FeatureSiteTemplateAssociation element to you stapling Feature which explicitly staples the Feature to STS#1 in addition to GLOBAL.

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<FeatureSiteTemplateAssociation
Id="EACA8B4F-B626-4359-8440-62415404D9E8"
TemplateName="GLOBAL" />
<FeatureSiteTemplateAssociation
Id="EACA8B4F-B626-4359-8440-62415404D9E8"
TemplateName="STS#1" />
</Elements>

Now you see what needs to be done. However, you should also ask the question of whether you should use this approach. That really depends on the environment you are using. Certainly, there is the possibility that you to staple Feature functionality into Blank Site that would break the WCM content deployment scheme. You have to watch out for that. However, if you can make assumptions that you are not causing problems in a specific environment with the MOSS content deployment scheme, then workaround can provide an effective means for provide a common initialization for all new sites inclujsing those created from the bland old site template known as Blank Site.

 ‭(Hidden)‬ Admin Links

make some noise