Logging to the SharePoint Log Files

Thanks to Brad Younge for sharing this a while back.  Below is an example on how to write to the SharePoint log files (located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\LOGS folder).

catch(Exception e) 
{
   Microsoft.Office.Server.Diagnostics.PortalLog.LogString("Exception: {0} - {1}", e.Message, e.StackTrace);
}

You’ll likely want to prefix your log entries with a date and time stamp.

Advertisements

DisableLoopbackCheck – Unauthorized (401.1) Exception calling Web Services in SharePoint

Published on 10/14/2008

After upgrading to .NET Framework 3.5 Service Pack 1 on my SharePoint web servers I began to get the following Unauthorized exception.

Type: WebException, Exception Message: The request failed with HTTP status 401: Unauthorized.

This error really has nothing to do with SharePoint, and is really just an IIS web services related item.  This problem is due to an added bit of security included in the .NET Framework 3.5 Service Pack 1.  Here is the Microsoft KB article explaining the issue and how to work around the problem.  This Microsoft article refers to the problem coming after applying other service packs for Windows XP and Server 2003, but .NET Framework 3.5 Service Pack 1 is also now using this same bit of added security – the loopback check.

You will likely not encounter this problem on a single web server configuration and if you are using the server name to access the web site.

However, most enterprise SharePoint farms consist of at least two web servers that are load balanced.  This is where the problem exists.

Likely Cause:

  • You are calling your web services from your web servers using the load-balanced URL, not the server name.

This isn’t a bug.  There was a security fix built into the Windows networking stack that prevents a machine name that resolves to the loopback address from accepting a connection unless that machine name matches the NETBIOS name.

One option is to use the server name instead of the load balanced IP.  This should remedy the problem.  However, the standard method to apply configuration changes across a SharePoint farm is via SharePoint solution files.  This usually requires the configuration entries to be the same across all the web servers in the SharePoint farm, and using the load balanced URL is likely the most appropriate.

Suggested configuration changes to resolve this:

  • Add the DisableLoopbackCheck registry entry discussed in this Microsoft KB article.  Note: you will need to reboot your server before the DisableLoopbackCheck takes effect.
  • Be sure to add your load balanced host name for your web farm to the Hosts file on each front end web server.  Use the loop-back IP address (127.0.0.1).  This will ensure that each web server looks at itself to access the web services preventing any trips back out to the load-balancer – and possibly calling the web service another web server in the farm.  This will be much less efficient.
    • If this problem appeared to be inconsistent (sometimes erroring, sometime successful), this is most likely due having multiple web servers.  The call to the web service will be successful if by chance the load balance redirected the call to the same (self) web server to access the web service.  It will fail when trying to call across to a different web server.

References:

I’m mentioned (twice) in an MSDN Magazine article – SWEET!

It is an exciting moment to have two articles on my blog discussed and referenced in the May 2008 edition of MSDN Magazine.  Thanks to Ethan Wilansky for a great article in MSDN Magazine, and for making this happen!

MSDN-Mag-May2008CoverHere is the link to the MSDN Magazine article:
MOSS 2007: Automate Web App Deployment with the SharePoint API

Here are the links to two of my blog articles that are referenced in this MSDN Magazine article:
How To: Create a SharePoint Solution for an InfoPath Form 
How To: Modify the web.config file in SharePoint using SPWebConfigModification

Also, Shawn Feldman, a coworker, was mentioned for his terrific work in deploying SQL Reports.

Apply a Theme to all sub sites in SharePoint 2007

Apply a Theme to all sub sites:
(works for MOSS 2007 only, not WSS 3.0)
  1. Change the top site to the theme of your choice using the normal method in Site Actions > Site Settings > Site Theme.
  2. Navigate to the top site to see the newly applied theme.
  3. View the HTML source of the SharePoint page using the theme you want.
  4. Look for a link tag containing the .css file for the applied theme.  It will look something like this:
    <link rel="stylesheet" type="text/css" id="onetidThemeCSS" href="/apps/afe/_themes/Belltown/Bell1011-65001.css?rev=12%2E0%2E0%2E4518"/>
  5. Copy the href value to your clipboard or to a text file if you like.  It should look something like:
    /apps/afe/_themes/Belltown/Bell1011-65001.css
  6. On your top level site, go to the Site Actions > Site Settings > Master Page screen.
  7. Scroll to the bottom where the Alternate CSS URL section is.  Select the "Specify a CSS file…" option.
  8. Paste the path copied from the href above into the text box.
  9. Check the Reset all sub-sites to inherit this alternate CSS URL option.
  10. Click OK.
  11. Navigate to your sub-sites and verify the theme has been applied.

SPSecurityTrimmedControl: Conditionally display contents by security

The SPSecurityTrimmedControl control will conditionally render the contents of this control to the current user only if the current user has access to the permission defined in the PermissionString.  The content can be any HTML code or control you like.  The PermissionString attribute defines the permission required to view the contents.  These Permissions are the same base values that are used in various combinations to the define the default Permission Levels that are created with each new site collection such as Design, Contribute, Read, etc…  You can also create your own custom Permission Levels for use in configuring your SharePoint security.  But remember, the PermissionString attribute can only be supplied valid Permission values, not Permission Levels.  There are 33 base SharePoint Permissions (Permission levels and permissions) of which any of these can be used.

This is a terrific control for use with your custom master pages and even with any custom SharePoint .ASPX pages you are hosting in SharePoint.

Attributes:

  • PermissionString: (required)
    Defines the permission values required to render the contents.
  • PermissionContext (optional):
    Enumeration Values:
    – PermissionContext.CurrentFolder
    – PermissionContext.CurrentItem
    – PermissionContext.CurrentList
    – PermissionContext.CurrentSite
    – PermissionContext.RootSite
  • PermissionMode (optional):
    Allows you to define whether All permissions are required or Any permission is required to render contents.
    Enumeration Values:
    – PermissionMode.All
    – PermissionMode.Any
Example:
<Sharepoint:SPSecurityTrimmedControl runat="server" PermissionsString="AddAndCustomizePages">
You can place any text or HTMl in this section. Only users having the AddAndCustomizePages permission will see this.
</SharePoint:SPSecurityTrimmedControl>
If you need to, you can even create your own Security Trimmer as shown here. 
http://msdn2.microsoft.com/en-us/library/aa981236.aspx

Another method worth noting is the RightsSensitiveVisibilityHelper.UserHasRights method. 
https://msdn2.microsoft.com/en-us/library/ms465624.aspx

References:

PermissionContext Enumeration (Microsoft.SharePoint.Utilities) 
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.utilities.permissioncontext.aspx
SPBasePermissions Enumeration (Microsoft.SharePoint)
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.spbasepermissions.aspx
PermissionMode Enumeration (Microsoft.SharePoint.Utilities)
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.utilities.permissionmode.aspx
Permission Levels and Permissions 
http://office.microsoft.com/en-us/sharepointtechnology/HA101001491033.aspx 
SPSecurityTrimmedControl Class 
http://msdn2.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.spsecuritytrimmedcontrol.aspx 
DLC's SharePoint Platform Team Blog 
http://www.sharepointplatform.com/teamblog/Lists/Posts/Post.aspx?ID=31

How To: Create a SharePoint Solution for an InfoPath Form

Mark Wagner
 
Summary
This post discusses how you can create a SharePoint solution package to deploy an InfoPath form to your SharePoint 2007 farm.  No coding required.
 
Downloads
Overview
InfoPath forms are normally deployed manually using the Manage Form Templates administration tool in Central Administration.  These forms can also be deployed using the STSADM command.  Although both of these methods work perfectly well, they are not always the desired method.
 
Since the release of SharePoint 2007/3.0 there have been a few new utilities that provide an improved and simplified deployment experience.  I have personally created installer classes for use with a packaged .msi file to simplify the process of deploying many SharePoint solution packages at once using the SharePoint 2007 object model.  The problem is that I have been unable to deploy an InfoPath form to SharePoint via the object model.
The result is a quick and simple solution to create your InfoPath form solution packages…   Let SharePoint do it for you.
 
Concept
If you have ever deployed an InfoPath form to SharePoint 2007, you may have also noticed that a new solution package appears in the Solution Management screen.  The name of this mysterious new solution begins with “form-“, followed by something that probably resembles the name of the InfoPath form you installed using the Manage Form Templates administration tool.  Chances are you probably assumed it had something to do with your form but just weren’t sure.
 
The new solution named “form-SOMETHING-NNN” is actually a solution package created by your SharePoint server that contains your new InfoPath form.  This allows your InfoPath form to be deployed and retracted to the web applications of your choice just like any other solution.
 
So, wouldn’t it be nice to see what that package looks like?  Heck, it would be even better if you could use that package to redeploy your form (as a solution package, not as an InfoPath .xsn file) to other SharePoint environments such as your Integration Testing, User Testing, and eventually on to your production environment.  The only question remaining is how do you export that solution package out of your SharePoint farm?
 
This is why I created the SharePoint Solution Exporter tool.
 
SharePoint Solution Exporter
The SharePoint Solution Exporter is a very simple little tool that allows you to export and save any solution installed on your farm to your local disk.  Once you have exported your solution (.wsp) file you can rename it to a more appropriate solution name for easy and clear identification; and you can take that solution and deploy it to another farm.  Here is what the SharePoint Solution Exporter tool looks like:
 
SharePointSolutionExporter
 
You must run this tool locally on your SharePoint web server.  To export a solution package:
  1. Enter the URL to your web server and click the Go button.
  2. A list of installed solutions will appear in the list body.
  3. Select the solution of your choice.
  4. Click the Download Solution File and specify name of your solution file in the Save As dialog.

I hope you find this tool as helpful as I have.

Note: For those of you interested in how to create a SharePoint solution package from scratch using Visual Studio, I hope to post an article soon on how to accomplish that as well.

How To: Hide/Remove the View All Site Content link in SharePoint

by Mark Wagner

Summary

This article covers how to hide (remove) the View All Site Content link and/or the Recycle Bin link from the quick launch navigation without having to customize the master page.  Additionally, I cover how I accomplished along with other options, all using the standard functionality provided in Windows SharePoint Services 3.0.

Important: This solution is not an answer for security.  The user will still have access to the View All Site Content page.  The View All Site Content link is simply removed or hidden from all the pages on the desired web site.

Applies To

This solution work on both Windows SharePoint Services 3.0 or SharePoint Server 2007.

  • Windows SharePoint Services 3.0
  • Microsoft Office SharePoint Server 2007
  • Sorry, but this does not work with SharePoint 2010. I have no plans at this time to update it to work with SharePoint 2010, but would like to eventually. Please reply below if you are interested in a SharePoint 2010 version and I may get motivated to upgrade it. :)

Licensing

  • There is no license required to use the Hide View All Site Content feature.
  • This is available to the public (business or personal) for free.
  • There is no support.
  • There is no implied or explicit warranty.
  • Use at your own risk.

Downloads

No Coding Required

  • Very easy to install
  • No coding required
  • For those interested in how to install this solution, it is very easy and does not require any coding, compiling, or editing.
  • Detailed installation and activation instructions can be found at the bottom of this article.

What Is The User Experience?

(What does it look like?)

Before (Normal)
After (Hidden)
VASCNormal
VASCHidden

Additionally I add a new custom menu item to the Site Action menu.  Here is the result of the new link.  This link will only appear for users having the AddAndCustomizePages right such as designers and administrators.

VASCSiteActionMenu

And finally, this functionality is wrapped up into feature allowing it to be activated or deactivated for each site as needed.  Here is the new feature that will appear in the list of Site Features for a web site.

VASCFeature

All of this is wrapped in to a single SharePoint solution package (.wsp) file and can easily be installed on a SharePoint farm by a server administrator.

How Does This Work?

The remainder of this article is dedicated to those who want a deeper understanding of how this solution works. Installation instructions are also located at the end of this article.

Note: From this point forward in the document, any reference to the “View All Site Content” link will be abbreviated to “VASC”.

Consideration

There are a couple ways to in which to accomplish this.  The first and most obvious method is to modify the master page that contains this link.  This involves a fairly simple process of modifying the master page and removing the VASC link, then redeploying the new master page.  The drawback from this is that you do have to modify the master page which is usually not desirable. Plus, the master page is likely to have more than one site based on it, and it may be desirable to have this View All Site Content link remain on those sites.

However, if you are willing to modify the master page, there is another posting you may find of value.  Keep in mind the security you define in the master page will be the same for all sites on your SharePoint farm.  If that is desirable, you may find this post on SPSecurityTrimmedControl: Conditionally display contents by security of use.

My Approach

I had a couple goals I wanted to my solution to meet.  They were:

1.       To be able to selectively choose the sites where the VASC link is hidden.

2.       Avoid having to modify the master page if possible.

3.       Provide a simple way for users to hide/remove the VASC link.

After a little investigation, a few things about SharePoint (3.0/2007) surfaced that allowed me to achieve all of my goals and provide a solution that can easily be implemented.

Hidden by Style

The approach I have decided to use is to simply hide the VASC link using a style sheet modification.  The VASC link for most, if not all of the sites assigns an ID (ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll) to the anchor tag containing the VASC link.  This makes it easy pretty darn easy hide this link by simply adding a bit of style code to the page.  In fact, just for giggles, you can copy the following style sheet code into a Content Editor Web Part.  This web part can even be strategically placed at the bottom of the page; optionally hide the title bar and nobody would even know it was there.  Here is the sample style to try it just for fun.  This will hide the View All Site Content link on your page.

#ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll
{
Visibility:hidden;
}

But this is not really good enough.  At least, not alone this isn’t.

I needed a way to do this for every page on a given site.  And copying this code to each and every page on a site is not only extremely tedious; it is almost guaranteed to be incomplete and error prone.  Microsoft Office SharePoint Server (MOSS) 2007 does provide an easy way to do this, but Windows SharePoint Services (WSS) 3.0 does not.  Using MOSS 2007, you can apply a custom style sheet to a web site and optionally apply it to every sub site.  For SharePoint servers where this is desired, and if you are using MOSS 2007, this will work for you.  Also keep in mind; you just removed the VASC link for every user – including your site designers and administrators.  Although this is not the worst of all problems, it is probably not the absolute desired solution either.

I still like the idea of using the custom style code to hide my VASC link.  But I also need to place a link on the page for users who will need easy access to the VASC link such as designers and administrators.  I know I can easily accomplish this by adding an access controlled link to the Site Actions menu, but I will come back to this in a moment.  I still need to address how to easily apply a customized style to every page on a given site.

CustomizeCss

So how can I apply a custom style to every page on a given site?  SharePoint provides a way to do this using the SharePoint object model.  With a bit of custom C# code I use the SPWeb.CustomizeCss method to specify a custom style sheet to be used on every page of my site.

The CustomizeCss method on the SPWeb class provides way to specify the style sheet file name of an existing style sheet used by SharePoint.  SharePoint utilizes a number of different style sheet files.  The one we are interested in is the style sheet file that is applied to each and every page on the site.  One such style file is the core.css file, and this will do just for our needs.  The standard default core.css file is located in …\12\TEMPLATE\LAYOUTS\1033\STYLES.  This STYLES folder is a virtually mapped via the /_layouts virtual directory that is mapped to each and every site in SharePoint.  So, the core.css file is accessible to every site by simply using the URL of “[site-root-url]/_layouts/1033/styles/core.css”.  For every page that SharePoint renders, it renders a link to the core.css using this path.

However, for any site that has been configured to use a custom core.css style sheet via the CustomizeCss method on the SPWeb class, the URL rendered in each page references a core.css file located in a different location.  This is accomplished in C# by the following code where web is an instance of the SPWeb class for the web site of your choice.

web.CustomizeCss(“core.css”);
web.Update();

The CustomizeCss(“core.css”) statement tells SharePoint to use a custom copy of the SharePoint core.css file.  Once this CustomizeCss method is executed, a copy of the core.css file found in the …\12\TEMPLATE\LAYOUTS\1033\STYLES folder is copied to the folder (not a document library) named _styles on the applied site.  The resulting URL to this new core.css file can be found at
“[site-root-url]/_styles/core.css”.  Modifying this core.css file will affect only the current site.

Reverting this site back to using the original global (un-customized) copy of the core.css file can be accomplished just a easy using the following code.

web.RevertCss(“core.css”);
web.Update();

Executing the RevertCss method does not remove the custom core.css file on the web site’s “/_styles” folder.  It simply tells the site to no longer use it and to use the original core.css found in the C:\…\12\TEMPLATE\LAYOUTS\1033\STYLES folder; which is the same folder as the as the “[site-root-url]/_layouts/1033/styles” folder.

So we now know how to use the CustomizeCss and the RevertCss methods on the SPWeb class provide an easy way to point the site to a new custom style sheet file.  Now that we have an easy way to point our site to a custom core.css file, all we need to do is copy our custom core.css file that contains all the original core.css contents plus the extra style code to hide the VASC link and copy it into the _styles folder of the site.  All of this can easily be implemented using a SharePoint feature.  Using a feature provides a standard way to enable or disable functionality with a site in a safe and secure manner.  I won’t cover all the details on how to create the feature here, but the source code provides all the code you need.

Now that we know how to hide the View All Site Content link easily using a feature and the CustomizeCss and RevertCss methods, we need to provide an easy way to allow site designers and administrators to quickly and easily use the View All Site Content link.

Site Action Link

To provide web managers such as designers and administrators with a convenient link equal to the View All Site Content link, we will add a new custom action menu item.  I won’t go into the details of the code and how to create the feature here, but I will briefly cover the expected functionality.  Again, the source code is available for those interested in the technical details.

The Site Action is usually located in the upper right corner of the web site and contains links used by site administrators such as the Site Settings link.  The nice thing about the Site Actions menu is that it is collapse and consumes a minimal amount of screen real estate.  So, adding an additional menu option to the Site Actions menu will not only be convenient for site administrators, it’s pretty easy to implement in a SharePoint feature.  This new View All Site Content link on the Site Action can be secured in a manner that best suits your needs.  In the solution sample I provide, this new View All Site Content link on the Site Actions menu is only visible to users who have the “AddAndCustomizePages” right which allows designers and administrators to see it, but is not visible to typical users of a site.

There are plenty of examples on how to add a custom item to the Site Action menu so I will not cover that in any detail here, but the solution sample I provide does include all the code – and the nice thing is, it isn’t much code.

Installation and Activation

Basic Install Steps:
1 – Add the solution using the STSADM command:
stsadm -o addsolution -filename [path]\VASCSiteAction.wsp

2 – Deploy the solution using the STSADM command:
stsadm -o deploysolution -name VASCSiteAction,wsp -allowgacdeployment -immediate –allcontenturls

3 – Optional – to restart IIS:
iisreset /noforce

Activating the new feature:
1 – Navigate to the site you want to hide the View All Site Content link.
2 – Go to the Site Settings for that site (Site Actions > Site Settings).
3 – Click the Site Features (not the Site Collection Features) link under the Site Administration section.
4 – Activate the new feature named “Hide the View All Site Content link”.

Your View All Site Content link should now be hidden and the View All Site Content link should now appear in the Site Actions menu.

Conclusion

The result is a single feature that a site administrator can activate and deactivate on any web site to hide and show the standard View All Site Content link in the quick launch navigation.  Additionally, it adds a useful new View All Site Content to the Site Actions menu that is visible only to users having the AddAndCustomizePages right on that site.

References

How To: Modify the web.config file in SharePoint using SPWebConfigModification

by Mark Wagner

Summary
 
SharePoint 2007 (WSS and MOSS) allows you to easily and safely add and remove modifications to the web.config file. This post briefly covers what the SPWebConfigModification class can do for you, and how to best to use it.

I hope to improve this post with additions, corrections, and contributions from the public, so please provide any constructive comments and suggestions you have.

Technologies this applies to:

  • Windows SharePoint Services 3.0 (WSS 3.0)
  • Microsoft Office SharePoint Server 2007 (MOSS 2007)

Acknowledgements

While I was scavenging for any information I could find regarding the SPWebConfigModification, there were a few posts I found useful. Information seemed to be scarce and I ended up learning most through trial and error; however, there a couple good nuggets and others I must achnowledge.

  • Shawn Feldman is a coworker (very sharp developer) who was the first to make me aware of the SPWebConfigModification class. Additionally, he provided me with the original code samples, some of which I have since modified and included in my WebConfigurator helper class (a separate post to come).
  • Vincent Rothwell has a post entry that provides, in my opinion, a “Best Practice” on how to best remove your modifications using SPWebConfigModification. It’s simple and right on target.
  • Antonz has a post entry that addresses the proper way to create a section that can be removed.
  • Daniel Larson also has a few a posts that provide a basic overview and examples on how to use SPWebConfigModification.

Overview of SPWebConfigModification

Through the use of the SPWebConfigModification class and xpath you can safely add and remove modifications to the web.config file. There are a number of benefits to using SPWebConfigModificaton to modify the web.config.

SharePoint provides access to a SharePoint web application via the object model using the SPWebApplication class. The SPWebApplication class has a SPWebConfigModifications collection property that contains all the modifications (SPWebConfigModification objects) made to this web application’s web.config file. This is also where we can add new modifications and have them applied to the web.config – or remove them. Additionally, you can iterate through this collection and inspect what changes have been applied. This contains all changes – including yours and those made by other assemblies. You can determine (or attempt to determine) where each change was made by inspecting the owner property.

Every modification has an Owner. Every change made the web.config can be assigned an owner. The owner is nothing more than a string value that uniquely identifies your changes from any other changes that have been made, or may be made in the future.  I suggest using the name of the assembly, or the feature name or feature ID.

Removing is not merely changing a value. By assigning an owner to each new change you make, you can very easily remove your changes. In the case where your original modification was an addition, where you added a new node or attribute, your changes are simply deleted and remove from the web.config file when they are removed. In the case where your modification changed the value of an existing node, upon removing your modification SPWebConfigModification automatically assigns the appropriate previous value. For example, let’s say we wanted to change the Trust level in the web.config to “Full” from whatever it currently is. The Trust level is usually set to a value of “WSS_Medium” by default, but it could easily be some other value before we make our changes. The great thing is that we don’t need worry about what the current value is if ever we need to remove our modification. We do this by removing our change, not by trying to change the value back to a predetermined value such as “WSS_Medium” – SPWebConfigModification manages this for us. This is a big advantage.

Propagate your web.config changes across the farm. SharePoint is designed to be very scalable and easily scalable. The changes you make to the web.config will need to be made to every front-end web server in the farm. SPWebConfigModification can manage this for you very easily.

Also, features are likely the method you will want to use to apply your changes. Using a feature (that can be either hidden or visible) will ensure your web.config changes are applied if a new web server is added to the farm, or rebuilt from scratch. Applying your web.config changes via a feature will ensure your changes are applied to new or newly built web servers – without having to refer to documentation or manually apply your changes to the web.config file on each and every web server.

SPWebConfigModification properties

SPWebConfigModification on MSDN

Name
Gets or sets the name of the attribute or section node to be modified or created.  This is an XPath expression relative to the parent node (specified by the Path property). Sometimes this is nothing more than the name of the new or existing node you want to change. For example: “pages”.

However, this often times needs to contain an XPath expression that is more spcific in order to properly specify the correct node to modify (if it exists) or to create.  For example: “add[@assembly=’myAssemblyName’]”

Owner
Gets or sets the owner of the web.config modification. This should to be a unique string value that will allow you to uniquely identify your modifications from any other modifications made to the web.config.  Suggestions are to use the assembly name, feature name, or feature ID.  This will ensure you are able to easily and cleanly remove your modification when the need arises.

Path
Gets or sets the XPath expression that is used to locate the node that is being modified or created. This value usually contains simple XPath expression to the parent node of the item you intend to change or create. For example: “system.web/httpHandlers” or “system.web/customErrors”.

This can also be a more specific XPath expression to select (or create) a node with a specific attribute value. For example:
“configuration/configSections/sectionGroup[@name=’mySection’]”

Sequence
Gets or sets the sequence number the modification. I have not performed any detailed testing with this parameter. I have always just set this value to zero (0) with no problems.

Type
Gets or sets the type of modification for this object instance. The three values available are defined via the SPWebConfigModification.SPWebConfigModificationType and are EnsureChildNode, EnsureAttribute, and EnsureSection. Caution: Use the EnsureSection type with prudence as nodes created with EnsureSection cannot be removed. See Best Practice section below.

UpgradedPersistedProperties
Gets the collection of field names and values for fields that were deleted or changed. I have not investigated this property and do not know of any need for using it. (inherited from SPAutoSerializingObject)

Value
Gets or sets the value of the item to set. This is usually the complete xml element tag or attribute value for the node specified in the Name property (or as the name parameter in the constructor).

How to use SPWebConfigModification

Using SPWebConfigModification is very easy, which makes it even better.

Below is a quick example of code that changes the mode attribute to a value of “Off”. Here is a sample of what the web.config node might look like that this code would be modifying.

<configuration>
   <system.web>
      <customErrors mode="On">
   <system.web>
<configuration>

Here is the quick example that will change the mode attribute to “Off”. Comments are inline describing each section of code.

private void SimpleSample()
{
    // Get an instance of my local web application
    SPWebApplication webApp = new SPSite("http://localhost").WebApplication;

    // Create my new modification to set the mode attibute to "Off".
    // Example: <customErrors mode="Off">
    SPWebConfigModification modification = new SPWebConfigModification("mode", "system.web/customErrors");
    modification.Owner = "SimpleSampleUniqueOwnerValue";
    modification.Sequence = 0;
    modification.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureAttribute;
    modification.Value = "Off";
    // Add my new web.config modification.
    webApp.WebConfigModifications.Add(modification);
    // Save web.config changes. 
    webApp.Update();
    // Applies the list of web.config modifications to all Web applications in this Web service across the farm.
   
webApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
}

More examples can be found later in the article.  Additonally, I will be posting my WebConfigurator helper class that contains a number of helper methods to centralize and simplify commonly modified elements in the web.config file.

Best Practices

I found it difficult to fully understand exactly how to use SPWebConfigModification as well as how it should and should not be used, and how I should expect it for function. For this reason I have started a list of best practices when using SPWebConfigModification.

Saving your modifications

While first using the SPWebConfigModification class, everything was going fairly smooth with testing and deployment – as it usually does on the developer machine. Of course my development machine is a single farm configuration, which is standard. Executing my web.config modifications on my single server worked just fine. However, when I deployed my code to two other farm configurations, the changes were not being applied to the web.config on any web server. Searching on the Internet surfaced a few other comments posted by others who were experiencing the same problem.

So, to correctly apply your changes on any farm configuration, be sure to perform the following two steps in your code:

  1. Use the ApplyWebConfigModifications() method on the SPWebApplication object you are saving your SPWebConfigModification object to. I don’t understand why this works over the other way, but it solved the problem for me. Example:
    myWebApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();

    Note: This code did not work across the farm (I could not tell you why).

    SPFarm.Local.Services.GetValue< SPWebService>().ApplyWebConfigModifications();
  2. Execute the Update() method on the SPWebApplication object. This will serialize the web application state and propagate changes across the farm – including your web.config changes.
    myWebApp.Update();

So, whenever you want to save your modification to the web.config file, you should execute the following two statements.

// Save web.config changes.
myWebApp.Update();

// Applies the list of web.config modifications to all Web applications in this Web service across the farm.
myWebApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications(); 

Removing your modifications

You should remove your modifications by checking the owner property on each SPWebConfigModification object in the SPWebConfigModifications collection. There are many examples that demonstrate removing modifications by creating a new SPWebConfigModification object and then removing that object. A must simpler, cleaner, and safer method is to remove your original SPWebConfigModification object by checking the Owner property on the SPWebConfigModification object.  Credit goes to Vincent Rothwell for sharing this logic.  Here is an example:

public void RemoveConfiguration(string owner)
{
   if (myWebApp != null)
   {
      Collection<SPWebConfigModification> collection = myWebApp.WebConfigModifications;
      int iStartCount = collection.Count;
      // Remove any modifications that were originally created by the owner.
      for (int c = iStartCount - 1; c >= 0; c--)
      {
         SPWebConfigModification configMod = collection[c];
         if (configMod.Owner == owner)
            collection.Remove(configMod);
      }
      // Apply changes only if any items were removed.
      if (iStartCount > collection.Count)
      {
         myWebApp.Update();
         myWebApp.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
      }
   }
}

Creating Sections
(EnsureSection vs. EnsureChildNode)

When creating new section you should use the EnsureChildNode modification type value instead of the EnsureSection. This will allow you to remove your custom section when the need arises. Antonz also discovered this as well and has an earlier post worth mentioning. Here is an example of the two options, both creating a section node like this: <mySection></mySection>

This cannot be removed (using EnsureSection):

SPWebConfigModification mod = new SPWebConfigModification("mySection", "configuration");
mod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureSection;

This can be removed (using EnsureChildNode):

SPWebConfigModification mod = new SPWebConfigModification("mySection", "configuration");
mod.Type = SPWebConfigModification.SPWebConfigModificationType.EnsureChildNode;
mod.Value = "<mySection />";

Save Only Once per Event or Feature Activation

It is important to remember that when developing and testing on a single server installation of SharePoint there are many activities that are able to complete instantly.  However, when that same section of code executes on a SharePoint farm with multiple servers the time it takes to complete a given task is longer.  This is due to timer jobs and farm synchronization events that must occur.

For this reason, you should only execute the ApplyWebConfigModifications() method only once within a feature activation or event handler.  If more than one call to the ApplyWebConfigModifications() method is made in close succession you will likely get the following error:

A web configuration modification operation is already running.

This is because request to save your changes from the first call to the ApplyWebConfigModifications() is not fully completed across the farm.

SPWebConfigModification Sample Feature

I intend to post a blog entry containing code samples of my WebConfigurator class and a sample of how to implement SPWebConfigModification using a web application feature.

Related Posts

WebConfigurator – a helper class to assist in using SPWebConfiguration.

References

WSPBuilder: SharePoint developers – Go Get It!

Building SharePoint solution files can be a complex and time consuming chore.  Yet, learning the details on how to create and package your own SharePoint solution package (.wsp) file is something every SharePoint developer should know.
 
Thanks to Carsten Keutmann, the time it takes for you to create a SharePoint solution package has just been drastically cut.  Keutmann has created a tool called WSPBuilder that makes packaging a .wsp file so easy – you simply cannot go without it.  It will save you many, many, hours of development time.  For example.  I needed to package up Telerik controls for use in SharePoint.  This literally took me about 10 minutes.  Ten minutes to package about 1286 files in 142 folders, create the .ddf file, create the manifest.xml file – of course, I didn’t have to do any of this.  The effort to do this by hand would have taken me several hours.
 
Great tool Keutmann!  Developers, you’ll find it on CodePlex – and you’ll be very happy to have it.

SharePoint Governance Plan and Checklist documents

SharePoint 2007 Governance Checklist Guide (whitepaper)
 
SharePoint 2007 Goverance Checklist GuideJust wanted to post about a SharePoint Governance Checklist guide on TechNet that I was able to contribute to.  A big thanks goes to Joel Oleson for assisting in making this contribution more widely known.  You can find it on TechNet at:
http://technet2.microsoft.com/Office/en-us/library/0dedd9b9-040e-4efd-95f0-6ebd5e4b033b1033.mspx?mfr=true
Personal copies are also located here:
https://markwagner1.files.wordpress.com/2014/09/sharepoint-2007-governance-checklist-guide.pdf
http://dl.dropbox.com/u/7124415/BlogFiles/SharePoint%202007%20Governance%20Checklist%20Guide.pdf