ASP.NET 2.0 Tag Mapping

on Tuesday, May 4, 2010

SharePoint auth provider web.config settings

Check this out:

Automatic NTLM auth with Firefox

on Thursday, April 29, 2010

Being a dedicated Firefox user, one of the few things that was still thwarting me was SharePoint.  We use SharePoint internally for a ton of stuff, and it was a drag to have to fall back to that other browser.  SharePoint pages look and work fine in Firefox, but I was having to reauthenticate on every single page, which really hindered my enjoyment of the experience.
I finally figured out how to get Firefox to do NTLM, which means I don’t have to deal with the authentication dialogs, thereby reducing my dependence on IE to one and only one application (Oddpost). 
It’s not at all obvious how to make it work, and it took me a few tries.  You have to go to your Firefox address bar and type about:config.  This will bring up the internal config editor, which allows you to set all kinds of properties that influence Firefox’s behavior.  Look for the key called network.automatic-ntlm-auth.trusted-uris.  Set that key’s value to a comma separated list of servers you want NTLM auth for.  So if your internal SharePoint sites are on servers called Larry and Mo, use “larry,mo”.  You can also add the same value to the key network.negotiate-auth.trusted-uris.  It’s unclear to me if that second one is required, but I set it, and everything works.  Now SharePoint works like a champ, and authenticates automatically.

Update Site Quota for existing sites- Tips & Tricks

on Wednesday, April 28, 2010

There is a little known discrepancy in the SharePoint 2007 Site Quota Templates; they are not easily updated. You see Site Quotas are based upon a template model that is disconnected in nature. That means that all new sites that have the template applied will get the updated version but any existing sites for which it was previously applied retain the previous values.

Unfortunately when you make changes to the template in Central Administration and then check the site quota of an existing site it does appear that the changes have taken effect. This is because the page is simply pulling the settings from the new Quota Template instead of pulling the settings applied at the site level. If you use StsAdm.exe to enumerate through the sites you will see that the site quota retains the previous values. I'll demonstrate.

Lets edit an existing Quota Template for Personal Sites. You navigate to Central Administration and click on Quota Templates. You can see that the existing values are set to allow a maximum storage limit of 100 MB.


Now change the Storage Limit Maximum to 200 MB as below.


If we navigate to Site Quotas and Locks and choose the MySites web application we can see that our changes have taken effect. Or so it would appear.


However, if we use Stsadm.exe and Enumerate through the sites in the web application though we can see that our initial value of 100 MB still applies.


This is because the Quota Template is just that, a template, it only applies to new sites that are assigned the quota from that point forward. It does not propagate its changes. Actually there really is no way to propagate these changes and of course we can't have that, so I wrote a little extension to Stsadm.exe to make that possible.

Rather than bore you with the specifics of how I did this I'll refer you to the blog that I used for references on extending Stsadm.exe. John Holiday has a great article here. And of course there is the trusty SDK with which I could not live without.

Below is a screen shot of the help for the Update Quota command that I wrote for Stsadm.exe.


As you can see it takes 2 parameters, one for the URL and another for the Quota Template Name. The command would be stsadm -o updatequota -url "" -quotaname "Personal Site".

After running the command we can go back and use stsadm to enumerate through the sites and see that our changes have taken effect.


Most everything in MOSS 2007 is extensible in one way or another and Stsadm is no exceptions. Actually extending stsadm is quite simple. In this blog entry I am going to walk through creating a custom extension for stsadm that I use in a real life scenario. This extension is called Quota Updater and you can read a little history about how this came about in my post here.

The first thing we do is create a new VS project and add a new class called quotaupdater.cs and implement the ISPStsadmCommand interface. Now we have to implement the Run and GetHelpMessage methods. These look like this:

public int Run(string command, StringDictionary keyValues, out string output)
//logic here
public string GetHelpMessage(string command)
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("-url <url>\t\tthe url of the site to process");
            sb.AppendLine("\t-quotaname <quotaname>\tthe template to process");
            return sb.ToString();

The second thing we have to do is create an XML file that describes our commands and add it to the 12/config directory. This looks as follows:

<?xml version="1.0" encoding="utf-8" ?>
    <command name="updatequotas"

          class="STSAdmExtensions.QuotaUpdater, STSAdmExtensions, 
      Version=, Culture=neutral, PublicKeyToken=86a65a77eee85b51">

In the above XML file the command name is whatever you would like your user to type to activate the custom command with stsadm. This does not necessarily have to be the same as your method or class. It can literally be whatever you would like. The class section is the typical stuff you can get by using Refactor on your assembly.

Now for the meat of the application. Basically what I wanted to do was get a reference to a site collection and a quota template and force updates to the template down to the sites on which it is applied. The Run method is as follows:

public int Run(string command, StringDictionary keyValues, out string output)
    StringBuilder sb = new StringBuilder();
    string url = keyValues["url"], quotaName = keyValues["quotaname"];
    //if no URL specified then return 0 and message
    if (url == null || url.Length == 0)
        output = "No url specified";
        return 0;
    //if no Quota Template name supplied then return 0 and message
    if (quotaName == null || quotaName.Length == 0)
        output = "No Quota Template specified";
        return 0;
        SPSite site = new SPSite(url);
        SPWebApplication webApp = site.WebApplication;
        SPSiteCollection col = webApp.Sites;

        SPGlobalAdmin globalAdmin = new SPGlobalAdmin();
        SPGlobalConfig globalConfig = globalAdmin.Config;
        SPQuotaTemplate quota = globalConfig.QuotaTemplates[quotaName];

        UpdateQouta(col, quota);
        output = message;
        //clean up resources
        return 1;
    catch (Exception ex)
        output = ex.Message;
        return 0;

And the UpdateQuota method is shown below.

/// <summary>
/// Updates all site quotas in a site collection with updated quota template values
/// </summary>
/// <param name="sites"></param>
/// <param name="quotaTemplate"></param>

public void UpdateQouta(SPSiteCollection sites, SPQuotaTemplate quotaTemplate)
    int iCount = 0;
    StringBuilder sb = new StringBuilder();

    foreach (SPSite site in sites)
        //verify quota on the site against the quota template to prevent overwrite
        if (site.Quota.QuotaID == quotaTemplate.QuotaID)
            site.Quota.InvitedUserMaximumLevel = quotaTemplate.InvitedUserMaximumLevel;
            site.Quota.StorageMaximumLevel = quotaTemplate.StorageMaximumLevel;
            site.Quota.StorageWarningLevel = quotaTemplate.StorageWarningLevel;
    if (iCount == 0)
message = "No sites were updated. Make sure you specified the correct " +_ "Quota Template Name.";
} else { sb.AppendLine(iCount + " Sites Updated"); sb.AppendLine("The Command Completed Successfully"); message = sb.ToString(); } }

Now all you have to do is deploy the assembly to the GAC and copy your XML file to the 12/config directory and you are set to go.

Host Multiple Websites using SSL on Port 443- WildCard Server Certificate

on Monday, April 26, 2010

Wildcard SSL certificates can allow you to publish multiple IIS web sites--all using SSL on port 443--that are accessible by host headers. That is, if you're running on IIS 6 or above.

So you read about these things, wildcard certificates, but mostly you read about how to buy them. It is possible (and easy) to create one for yourself, however, so long as you don't mind it not being trusted by folks' browsers.

There are some really good uses for these, not least in a test environment in which you don't care about the trust. Production environments need them, too, sometimes, such as when you're using a network appliance like a Netscaler or F5 load balancer. Those devices allow you to point multiple URLs (cnames, really) to a single (or multiple) server(s). Very handy. In our case, we have several web sites that we'd like to secure using SSL. Problem is: they're all on a single server.

There are several options for dealing with such a case: assign multiple IP addresses to the server, use different SSL ports for each IIS site, or (definitely the coolest option) use a wildcard certificate on the server to allow IIS to decipher the http host header. This option, by the way, is a new feature with IIS 6, so if there's anyone out there still using IIS v5, this is another reason to upgrade.

A little background on the problem might be in order: a SSL certificate is used to encrypt the http data. Normally, in setting up a IIS web site, we differentiate that site from all the others by assigning unique host headers to each site. IIS can use those host headers to determine to which site to route any given http request.
When the site is using ssl, however, the host header is encrypted, which introduces something of a chicken-and-egg thing: since the host header (along with all the rest of the data) is encrypted, IIS can't use that to determine which site to send the request to. And, since a SSL certificate is site-specific, IIS can't use a certificate to decrypt the data until it knows which site the request belongs to. Thus, it widely is reported that it isn't possible to have multiple SSL sites on a single server, all sharing the same port.

Enter wildcard SSL certificates and secure server bindings. The wildcard certificate allows IIS to use the same certificate for all of the sites on a particular port. That takes away the requirement that IIS know which site's certificate to use in decrypting the data. Secure server bindings help IIS in securing the wildcard certificate, a requirement for setting this up.
Note that a similar solution is available to apache. You can read about it here. Thus, it is very possible to have multiple SSL sites on a single server, all sharing the same port.

Configure your sites to use host headers

Host headers are the backbone of this. Open the properties window for each site in IIS and click the advanced button. There, you can add the appropriate host header on port 80.

Creating a self-signed wildcard SSL certificate:

The next step in this process is to make sure that all of the relevant sites have the same SSL port assigned to them. In IIS, go to each site's properties and enter the appropriate port number (the same one for each site) in the SSL Port field. 443 is the default SSL port.

Note that once you do this, all but one of the affected sites will stop. That is because, at this point, IIS isn't configured to allow multiple sites to share the same SSL port. That's OK; we'll take care of that in a moment.

Now, to generate the certificate: using SelfSSL, generate the certificate for one existing IIS site. SelfSSL is a tool that's a part of the Microsoft IIS Resource kit. If you haven't downloaded and installed it, you'll need to do that first. Here's the syntax:

selfssl /n:cn=* /s:1 /P:443 /v:3650

Where * would be your own URL. So if you had these sites:
you'd use this code:

selfssl /n:cn=* /s:1 /P:443 /v:3650
It's the * that makes it a wildcard certificate.

The /s:1 is the site identification. There are a variety of ways to view a site's identifier, but the easiest simply is to open the IIS manager and click on the "web sites" tree on the left. The right-hand pane will show the description and identifier. The default site has an identifier of 1; the other sites have very long identifiers.

/P: is the SSL port you're using, and /V: is the number of days for which this cert is valid. Why would you want it to expire, anyway?

Now you've generated a wildcard certificate.

Assign the Certificate to your sites

The easiest way to assign a certificate to a site, having already created it, is to view the site properties in IIS Manager. Click on Directory Security, and then on the Server Certificate button. This will start the wonderful wizard of IIS.

You already have created a certificate, so when the wizard prompts you, choose "Assign an existing certificate." When you click next, you'll see a list of available certs, including the wildcard certificate you created. Select this certificate, click next, and make sure you assign it the same port that was assigned to the first site.

That's it: once the wizard has finished its magic, you've assigned the cert to your site. Repeat this for all of the sites you want to secure on this port with SSL.

Configure Secure Server Bindings

This is the final step. It involves running a vbs script to set up secure bindings, which allows IIS to use host headers with SSL and secure the new wildcard certificate you created and installed.

The syntax is like this:

cscript adsutil.vbs set /w3svc/844934796/SecureBindings ""

The adsutil.vbs script, at least on my systems, is at C:\Inetpub\AdminScripts. You'll need to run the script command from that location.

The syntax breaks down like this:
844934796 is the site ID. Substitute your own site identifier there.
443, again, is the port is the host header for the site. Make sure that you have this host header configured in the site properties in IIS, as well.

Run this script for each of your IIS sites.

That should be all you need to do. Start up the stopped sites after you've run cscript, and you should be good to go.

Microsoft has a few documents that run through this, but they don't really put the pieces together for you. Here they are:

Configure SSL Host Headers (IIS 6.0)
Configuring Server Bindings for SSL Host Headers (IIS 6.0)
Obtaining and Installing a Wildcard Server Certificate

By the way: if you've done a lot of testing, and you've generated a bunch of certificates you're no longer using, you can delete them. Run mmc.exe and add the certificates snap-in. You'll want to choose the "local computer" version. Using that, you can manage all of your local certificates, including deleting the ones you no longer need.

How to create a browser cache save URL to a javascript or css file in SharePoint

on Monday, March 29, 2010

How to create a browser cache save URL to a javascript or css file in SharePoint

Often it is necessary to ensure that updates to files on the server get populated to the client asap. Especially when it comes to dependencies to custom javascript of CSS files and server controls.

SharePoint itself does this by adding a query string to some of its vital Javascript files. E.g.:


Whenever the core.js file changes on the server a new query string value is generated. That allows browsers to cache the file as long as the file does not change on the server.

Today I got the question if it is possible to utilize the same method for custom js and css files. The answer is yes.

SharePoint provides the functionality to generate browser cache save Urls for such files if they reside inside the _layouts directory or one of it's localized subdirectory using the following method:

public static string Microsoft.SharePoint.Utilities.SPUtility.MakeBrowserCacheSafeLayoutsUrl(string name, bool localizable)

The first parameter needs to be the filename without a path (e.g. test.css) the second defines if the file resides in a language specific subdirectory or directly in the _layouts directory.

The following code will (e.g.) create the output below for german locale:

string saveUrl = Microsoft.SharePoint.Utilities.SPUtility.MakeBrowserCacheSafeLayoutsUrl("my-own.js", true);


SharePoint Caching

Bring Cache

Depending on your user base you may care very little about how caching works in SharePoint. But whether you plan on using it or not, you should at least know it's there and that it takes very little effort to turn it on.

Remember that almost everything in SharePoint resides in the content database. This coupled with the fact that opening a database connection is an extremely expensive operation means that there's potentially a lot more capacity to be had from a SharePoint site by simply enabling caching.

In my experience running the Microsoft Web Application Stress Tool on test SharePoint sites, most sites running caching profiles were able to achieve 33% more requests per second that those using no caching at all. That's a LOT more capacity to be had, and best of all it's free (you've already paid a lot of money for MOSS).

To enable Page Output Caching you need to turn on both the Office SharePoint Server Publishing Infrastructure feature in the Site Collection and the Office SharePoint Server Publishing in the sub site. Disk Caching is turned on through the web.config.

Page Output Caching

Page Output Caching works a lot like ASP.NET page output caching, allowing you to cache pages in memory for a certain period of time and also maintain many cached versions of pages based off of Browser Type, Query String, HTTP Header, or some custom function that you write and implement in your pages. It's quite flexible.

You start off by defining Caching Profiles in Site Settings (that is, how you want to determined if something should be cached) and then assigning profiles to either of Authenticated or Anonymous users as they visit your site. For instance, you could choose to cache pages for anonymous users and not cache pages for authenticated users.

By default Cache Profiles inherit down to sub sites just like security, and like security you can change the inheritance at any sub site along the way.

Disk Caching

The other type of caching is Disk Caching which simply stores assets that you would normally fetch from the content database on disk. Disk Caching and Page Output Caching aren't mutually exclusive and actually marry quite well together. To enable disk output caching all you really need to do is open up the web.config for the site and change the BlobCache key to look like below:

<Blobcache location="C:\blobCache" path="\.(gif|jpg|png|css|js)$" maxSize="10" enabled="true" />

It's worth mentioning that path is a regular expressions of file types to cache to disk and maxSize is measured in gigabytes. The location is of course where these files will be persisted to disk.

Some Thoughts

I would strongly encourage you to enable caching schemes one or more of your SharePoint sites to try it out. Those that make the best candidates (stand to gain the most performance) are those that have a lot of users and have anonymous access turned on for the entire site collection (usually synonymous with public facing sites). If you think you're viewing a cached version of a page and you want to see the real content you can always suffix the query string with a nocache=1. IE. http://somedomain/Pages/default.aspx?nocache=1 displays the non cached version of default.aspx for the somedomain site.

So there it is. Enjoy your free performance gains. Like G.I. Joe says: "Knowing is half the battle."

Hide New Icon or Change the Duration SharePoint

on Friday, March 19, 2010

Use the command

Hide the Icon
stsadm -o setproperty -pn days-to-show-new-icon -pv 0 -url http://machinename/sites/teamsite.

Change the duration from default "2" days to "10"

stsadm -o setproperty -pn days-to-show-new-icon -pv 10 -url http://machinename/sites/teamsite.

Get All the Checkedout documents sharepoint

on Monday, March 15, 2010

using Microsoft.Office.Server.Search.Query;


ResultTableCollection rtc = null;
DataTable retResults = new DataTable();


string fullTextSql = "SELECT ModifiedBy,Title,owsCheckoutUser,FileExtension,owsFileLeafRef,Path FROM SCOPE() WHERE owsCheckoutUser IS NOT NULL"


 using (SPSite site = new SPSite(http://servername))

                    using (FullTextSqlQuery query = new FullTextSqlQuery(site))

                        query.QueryText = fullTextSql;
                        query.ResultTypes = ResultType.RelevantResults;

                        query.RowLimit = rowLimit;
                        rtc = query.Execute();

                        if (rtc.Count > 0)
                            using(ResultTable relevantResults = rtc[ResultType.RelevantResults])

                                retResults.Load(relevantResults, LoadOption.OverwriteChanges);


Mange WebPart Resources (Linked vs Embedded)

on Friday, March 12, 2010

One of the most common questions I get in class and see in the forums is how best to deal with Web Part resources. By resources, I mean those necessary files that your Web Part depends on. These include JavaScript files, images, CSS, Flash, or even Silverlight apps. With the packaging and deployment model of SharePoint, it may be challenging to figure out where to store and how to reference these files. This article will overview your deployment options and give you enough information to make the best choice for your resource needs.

Linked or Embedded

With resource files, you have two basic options: linked or embedded. Linked means your Web Part will point to the file that lives somewhere in the file system. This is the most common approach. Embedded means you store the actual resource file inside your Web Part assembly. While less common, this can be very useful in many cases. We’ll look at each of these in more detail.

Linked Resources

Linked resources work best if you’ll need to modify the resource file separately from the Web Part. For example, say your Web Part references a JavaScript file and you continually need to tweak it and don’t want to recompile and redeploy the Web Part. If you link to it, it’s easy to change, and no changes to your Web Part are necessary. When working with linked resources, SharePoint provides you two primary options.

  1. Store the resource in a virtual directory such as _wpresources (this points to C:\Program Files\Common Files\microsoft shared\Web Server Extensions\wpresources)
  2. Store the resource with the Web Application inside the inetpub\wwwroot\wss\VirtualDirectories\<80>\wpresources

For option 1, you should make sure your Web Part assembly is deployed into the GAC. This is necessary since the _wpresoures virtual directory is used across each SharePoint Web Application. We call this Farm-level scope.

For option 2, you should make sure your Web Web Part assembly is deployed in to the bin folder for the Web Application. We call this Web-Application scope.

That said, you choose which wpresources folder based on the scope of your Web Part. For both options, you’ll be placing your files inside a sub folder to keep them separate from other files in other Web Parts. The sub folder name needs to be the namespace of your project. For example, with Web-Application scope, it might go here: inetpub\wwwroot\wss\VirtualDirectories\80\wpresources\namespace.

Ok, so you’ve chosen the appropriate folder based on the scope. How would you then reference this file within your Web Part code? It’s actually pretty easy and would look like this for a JavaScript file. (Note: this code can be placed in the CreateChildControls method for the Web Part.)

//Path to resource.  This is used for a web part deployed into the GAC (Option 1)
string scriptUrl = "~/_wpresources/namespace/file.js";

//Path to resource.  This is used for a web part deployed into the bin folder (Option 2)

string scriptUrl = "~/wpresources/namespace/file.js";

//Reference Script for web page
Page.ClientScript.RegisterClientScriptInclude ("file.js", scriptUrl);
Be careful, as these are very similar. You’ll notice for the first one, that you specify _wpresources (with an underscore). Also, make sure you replace namespace with the actual namespace for your Web Part project. For an image, it would work like this:
Image myImage = new Image();
myImage.ImageUrl = "~/wpresources/namespace/image.jpg";


The last important detail when using linked resources is how should you deploy these files? First off, you should be using SharePoint Solutions to deploy your code. You are doing this, right? Inside the Solution manifest.xml file, there are specific tags to deploy these kinds of resources. The schema looks like this:

<Assembly Location="Namespace.dll" DeploymentTarget="WebApplication">   

      <ClassResource Location="file.js"/>
      <ClassResource Location="image.jpg"/>

Here is where you can see that the DeploymentTarget attribute matches the scoping option. In this sample above, it is WebApplication scoped (option 2). To deploy into the GAC, replace this with GlobalAssemblyCache. To learn more about the schema inside this file, see this link.

Now that you have a good grasp on linked resources, let’s take a closer look at those that are embedded.

Embedded Resources

Embedded resources are physically stored within the Web Part .DLL file. In one way, this is nice as you can always be assured that the resources and the Web Part stay together. The drawback is that if you need to change a resource, you must recompile and deploy an updated version of your Web Part. When the client needs the resource, it is dynamically extracted from the .DLL and provided. You’ll see how.

To use an embedded resource, there are three things you need to do. The first is that you need to add the resource file to the project and mark is as an Embedded Resource. This is done via the Build Action setting inside Visual Studio as shown here.


The second thing you need to do is declare this resource inside the AssemblyInfo.cs file for your Web Part project. This is an easy one-liner as shown:

[assembly: System.Web.UI.WebResource("namespace.file.js", "text/javascript")]

The parameter string that is used consists of the Web Part namespace followed by the filename of the resource. The next parameter is just the MIME type. If this were an image, it could be image/jpg.

The third thing step is make sure you extract the Url to the resource. This is also one line of code as shown:

string scriptUrl = Page.ClientScript.GetWebResourceUrl(this.GetType(), "namespace.file.js");

As with linked resources, you’ll then deliver this script to the page with a call to RegisterClientScriptInclude within CreateChildControls. As you would probably guess, the string here must match the name in the AssemblyInfo.cs file. As written here, the resource files need to exist in the root folder of the Web Part project. (Note: technically you don’t need to precede the file with the namespace as long as the string is unique within the project. The common convention, however, is with the namespace).

You might be curious how this actually works from the browser’s perspective. Well, what gets delivered to the browser is a link to a special, in-memory page called WebResource.axd along with a querystring to uniquely identify this specific resource. In HTML, it looks something like this:

<script src="/WebResource.axd?d=ZPJuqJGGI6qgSKsEa2PfIw2&amp;t=633527425956801634" 

This is how it dynamically finds the resource file, extracts it from the Web Part DLL, sets the content type, and then delivers it to the browser. Pretty cool.


In this post, you have seen how to both link to and embed Web Part resources. Each has its own advantages and disadvantages, mostly boiling down to whether you need to maintain the resource separately from the Web Part. In both cases, the resource file can be cached, so there is little performance difference from each option. Feel free to use one of these two approaches for your next web part.

SharePoint Usage Report using Object Model


It is a common requirement to gather information around the Windows SharePoint site usage. Organizations prefer to find out the popular sites in their organizations are or what external WSS sites attract the most number of visitors. This will provide information necessary for an organization to identify the important sites in their environment and properly manage them with extra resources if necessary.

One of the common complains around accessing theses data are the inflexibility of gathering information in a central location. The administrator will have to navigate to the selected SharePoint site administration pages to access the data. This will become a more time consuming exercise when the administrator need to collect usage data from larger number of SharePoint sites.

In this article, I am looking at creating an ASP.NET web application that will populate a collection of SharePoint sites in a drop down list for a given SharePoint site collection. The web application will display the usage details of the selected SharePoint site from the list. This will help the SharePoint administrator to gather all SharePoint usage data from a central location with out have to navigate many different SharePoint site locations.

Usage Analysis Data Web Report

Figure 1 display a Usage Analysis data for a Windows SharePoint site. The users have the option of selecting a monthly or a daily report.

Figure 1: Monthly Usage Analysis Report

Usage Analysis Processing Reports

First of all let's have a look at what is Usage Analysis Reports in SharePoint. Theses reports will help the organizations to determine how the web sites are used in their environment. The data is taken from IIS Logs on the front end web servers and stored in to temporary files. The data is merged in to the content database on the back end SQL Servers when the daily log processing takes place.

The Usage Analysis is not enabled by default when the organization deploys the Windows SharePoint Services Sites. Organizations should enable the Usage Analysis logging process on the servers when they require gathering usage information. The logs files are created daily and a flag is attached to mark that it has been processed.

These logs files are not automatically deleted, they are preserved in "local_drive (C) :\Windows\system32\LogFiles\W3SVC*" where * indicates the Internet Information Server (IIS) instance number of the virtual server as displayed in Figure2. Organizations should consider the advantages against the disk space storage before enabling the Usage Analysis service in their environment. The organization can stop logging process' any time they require to do so.

Figure 2: Preserved log files folder structure with W3SVC* format

By default the log files are located at "local_drive (C) :\Windows\system32\LogFiles\STS" directory. Separate folders are created under above directory for each virtual server and separate folders for each day as displayed in the Figure 3.

Figure 3: Separate directories for each virtual server and for each day

Organizations can configure the above Log file store path for their own preferred path and create up to 30 log files.
(Please look at Setting up Usage Analysis process for more details.) If an organization decides to store the log
files in their preferred location, they should grant Read, Write and Update rights permissions for STS_WPG user
group for the specified folder. Without the permissions, the usage log files cannot be created or updated by IIS.

Setting up Usage Analysis Processing

Administrators can control the setting of Usage Analysis process using the SharePoint Central Administration page. The user must be an administrator on the local server or a member of the SharePoint Administrators group to configure the analysis processing. If the organization adds a new virtual server after the analysis service been configured, they will need to reconfigure the analysis service to collect the data on the newly added virtual server.

  • Click "Start -> All Programs -> Administrative Tools -> SharePoint Central Administration"
  • This will open the "Windows SharePoint Services Central Administration" page
  • Select the "Configure usage analysis processing" from the "Component Configuration" section as displayed in figure 4

    Figure 4: Component Configuration section on the central administration page
  • The Configure Usage Analysis Processing page will open as displayed in Figure 5

    Figure 5: Configure Usage Analysis Processing page
  • Select "Enable logging" check box in "Logging Settings" section
  • The administrator can select a preferred file locations for the log files in "Log file location" box or use the default location C:\WINDOWS\system32\logfiles\STS
  • Enter the number of log files to create in the "Number of log files to create" box. This can be between 1 and 30.
  • Select "Enable usage analysis processing" check box in "Processing Settings" section.
  • Select the time range that analysis process should run from "Run processing between these times daily". By default this is set to start at 1am daily. The administrator can allocate a time period that won't affect the demand on the site.
  • Click "OK" to finish the configuration.

View Usage Analysis Reports

The user must be an administrator or have the View Usage Data right for a site to view the site usage reports. The reports are available through Site Administration page.

The usage data is collected and stored for the entire site collection on a server at a time. The users can see the total number of hits for a site collection on the Site Collection Usage Summary page and for more detailed information, Site Usage Report page for individual sites or sub sites usage information.

View Site Usage Report

  • Navigate to the site you prefer to view the report.
  • Click Site Settings on top tool bar.
  • Click Go to Site Administration link under Administration section as displayed in Figure 6

    Figure 6: Site Settings page
  • Click View site usage data link under Management and Statistic section in Top-Level Site Administration page as displayed in Figure 7

    Figure 7: Top-Level Site Administration page
  • The Site Usage Report page will open as displayed in Figure 8

    Figure 8: Site Usage Report page

Site usage reports are useful for identifying which content on Windows SharePoint Services sites are being heavily used or used very little. This will help organizations to understand which sites are candidates for archiving and which sites should be kept online. In addition, this report contains information regarding how much storage space WSS sites are using. This page provides a report that contains following information:

  • Pages that have been accessed on that site, including document libraries
  • Users that have access the site
  • Operating system of the user accessing the site
  • Browser type
  • Referrer URL
  • Data can be displayed by monthly or daily summary format

Figure 9: Different reports available

The users can select a report option and a daily or monthly option to generate a report. Figure 9 displays a monthly report of all the pages accessed and different kind of reports options available.

Code Example

The web page contains a text box to enter the SharePoint site collection URL. The appropriate sub site will be listed in a dropdown list when user clicks the Submit button. The user then have the option of viewing the daily or monthly usage report of a selected site.

First of all you will need to add the Microsoft.SharePoint.dll to your web application reference list.
This will give us the access to the SharePoint Object Model.

Then instantiate the SPSite object as displayed below. The absolute URL is passed in through
the txtWSSSiteUrl text box. This will populate site collection for the given URL.

//Get the site collection
SPSite mySiteCollection = new SPSite(txtWSSSiteUrl.Text);

Then to access an individual site, instantiate the SPWeb object as displayed below. I am passing in the site name as a parameter.

//Get the details of the selected WSS site
SPWeb site = mySiteCollection.AllWebs[siteName];

After constructing the site SPWeb object, developers can access the information of the site usage data using the public method "GetUsageData" of the SPWeb object as displayed in code example.

GetUsageData(Microsoft.SharePoint.Administration.SPUsageReportType, Microsoft.SharePoint.Administration.SPUsagePeriodType) Method.

The GetUsageData method of the SPWeb class returns a data table that contains information about the usage of a Web site based on the specified type of report and time interval.

SPUsageReportType Enumeration

The SPUsageReportType enumeration specifies the type of information returned in a usage report for a SharePoint site.

The following table shows the members of the SPUsageReportType enumeration and a brief description

browserThe type of Web browser used to visit the SharePoint site. All usage data refers specifically to visits from referring URLs external to the site.
osThe operating system used on the client computer. All usage data refers specifically to visits from referring URLs external to the site.
refUrExternal URLs through which users navigated to the SharePoint site.
urlURLs of pages that are visited or of pages for lists that are updated. Discussions about a page are counted as hits on that page.
userUsers who visited the site.

SPUsagePeriodType Enumeration

The SPUsagePeriodType enumeration specifies the time interval on which a usage report for a Web site is based.

The following table shows the members of the SPUsagePeriodType enumeration and a brief description

dayReturns usage information for each day during the past 31 days starting from the previous day
lastMonthSummarizes usage information for the last 31 days relative to the previous day

I am binding the data table return from GetUsageData property to a DataGrid control to display the information.

Accessing User daily report

//Users who visited the site
DGUsers.DataSource = site.GetUsageData(SPUsageReportType.user,;

Accessing User monthly report

//Users who visited the site
DGUsers.DataSource = site.GetUsageData(SPUsageReportType.user, SPUsagePeriodType.lastMonth);

Accessing Browser daily report

//The type of browsers used to visit the site
DGBrowser.DataSource = site.GetUsageData(SPUsageReportType.browser,;

Accessing Browser monthly report

//The type of browsers used to visit the site
DGBrowser.DataSource = site.GetUsageData(SPUsageReportType.browser, SPUsagePeriodType.lastMonth);

Accessing Operating System daily report

//The Operating System used in client computer
DGOs.DataSource = site.GetUsageData(SPUsageReportType.os,;

Accessing Operating System monthly report

//The Operating System used in client computer
DGOs.DataSource = site.GetUsageData(SPUsageReportType.os, SPUsagePeriodType.lastMonth);

Accessing refUrl daily report

//External URL client used to navigate to SharePoint site
DGRefUrl.DataSource = site.GetUsageData(SPUsageReportType.refUrl,;

Accessing refUrl monthly report

//External URL client used to navigate to SharePoint site
DGRefUrl.DataSource = site.GetUsageData(SPUsageReportType.refUrl, SPUsagePeriodType.lastMonth);

Accessing url daily report

//URL's of pages visited
DGUrls.DataSource = site.GetUsageData(SPUsageReportType.url,;

Accessing url monthly report

//URL's of pages visited
DGUrls.DataSource = site.GetUsageData(SPUsageReportType.url, SPUsagePeriodType.lastMonth);

Deploying the Web Application to the SharePoint Portal Server

  • Create the "UsageAnalysisData" Virtual directory under the portal web site in IIS
  • Map the virtual directory to the physical file path (this should be done as apart of above step)
  • Open the SharePoint Central Administration pages by clicking "Start > Administration tools > SharePoint Central Administration"
  • Click "Windows SharePoint Services" link on the left hand side
  • Select "Configure Virtual server setting" link from "Virtual Server Configuration" group
  • Select your Portal server from the list
  • Click "Defined managed path" link under Virtual Server Management group in Virtual Server setting page
  • Type name of the virtual directory you created in first step in the Path section of Add new Path section
  • Select "Exclude path" radio button under the type section
  • Click "Ok"
  • Then navigate to http://portal_site_name/UsageAnalysisData/MonitoringPage.aspx

Figure 10: A list of sub sites of the site collection

Figure 11: Daily Usage Analysis Report of a Windows SharePoint Site


SharePoint Administrators should be able to use this article as a starting point and develop their SharePoint Usage Analysis data gatherer web application according to their requirements.

Print ListData SharePoint

on Thursday, March 11, 2010

Solution Architecture

The solution will be deployed as a wss feature, which allows us an easy way to add a menu item to the sharepoint menus. The feature will define that the item we want to add will be added to the actions menu of all lists, in a site collection. You can ofcourse change it so that it behaves differently and connects only to lists of a certain type if you so wish, or maybe move the menu item to a different place. I recommend reviewing the msdn article on the possible configurations.
The solution is based on 3 files:

  1. feature.xml
    Defines the feature, its scope and its title that you will see in the "site features" (or site collection features or farm features - depending on the scope)

  2. PrintList.xml
    Defines what action we want to add to what menu and what will happen when the user clicks the menu item. This is where you configure the text of the item, and the link to the page that will print the list. which just happens to be the last file:

  3. PrintList.aspx
    Contains the code that shows the list in a print-friendly view. This file should be deployed to the layouts folder and must be called with the site's context (more about that shortly).

To the Code!

note - when I talk about the "12 hive" I am referring to the folder C:\Program Files\Common Files\Microsoft Shared\web server extensions\12

Create the page that prints a list:

  1. Log on to the server, and open the template\layouts folder in the 12 hive.

  2. Create a new text file in the folder, and name it "PrintList.aspx"

  3. Open the empty file in your editor of choice (notepad is fine) and paste the following code into it:

    <%@ Page Language="C#" Inherits="System.Web.UI.Page" %>

    <%@ Register TagPrefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"

    Assembly="Microsoft.SharePoint, Version=, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

    <%@ Import Namespace="Microsoft.SharePoint" %>



    <title>SharePoint List Print</title>

    <link rel="stylesheet" type="text/css" href="/_layouts/1033/styles/core.css" />

    <script type="text/javascript" language="javascript" src="/_layouts/1033/init.js"></script>

    <script type="text/javascript" language="javascript" src="/_layouts/1033/core.js"


    <script type="text/javascript" language="javascript" src="/_layouts/1033/ie55up.js"></script>

    <script type="text/javascript" language="javascript" src="/_layouts/1033/search.js"





    string listId = "";

    string referrer = "";

    //get the list id (guid in a string format) from the query string

    listId = Page.Request.QueryString["list"];

    //get the http referrer (for the back button\action)

    referrer = Page.Request.ServerVariables["http_referer"];

    //make sure the list parameter was passed

    if (listId == null)


    //if a referrer url exists (since the page may have been opened from a direct link, this is not always the case) redirect the user back

    if (referrer != null && referrer.Trim().Length != 0)


    Page.Response.Write("<p>The list ID parameter ('list') is missing from the address.<br>Please go to the list you want to print and try again.</p>");

    Page.Response.Write("<p><a href=\"" + referrer + "\" title=\"Go Back\">Click here to go back to the page you came from</p>");




    Page.Response.Write("<p>The list ID parameter ('list') is missing from the address.<br>Please go to the list you want to print and try again.</p>");







    //load the web object for the site that the page is now in context of

    using (SPWeb web = SPControl.GetContextWeb(Context))


    //load the list that was passed in the 'list' querystring parameter to the page

    SPList list = web.Lists[new Guid(listId)];

    //load the query of the default view. note - need to modify code in the future to enable multiple view printing

    SPQuery query = new SPQuery(list.DefaultView);

    //write the list to the page


    //add the print script


    <script type="text/javascript" language="javascript">






    catch (Exception ex)


    Page.Response.Write("<p>There was an error loading the list information:<br />");








Install the feature

  1. Open the \TEMPLATE\FEATURES folder under the 12 hive

  2. Create a folder called PrintListMenuAction

  3. In that folder, create 2 text files, one called feature.xml and the second printlist.xml

  4. In your editor of choice (notepad is fine) open the feature.xml file and paste into it the following:

    <?xml version="1.0" encoding="utf-8" ?>

    <Feature Id="769826dd-9dd2-11db-96ca-005056c00008"

    Title="Print List"

    Description="This feature adds a print command in the Actions menu for Windows SharePoint Services lists."





    <ElementManifest Location="PrintList.xml" />



  5. In your editor of choice open the printlist.xml and paste the following:

    <?xml version="1.0" encoding="utf-8" ?>

    <Elements xmlns="">


      <!-- Add the action to the List Toolbar Actions Menu Dropdown -->

      <CustomAction Id="SPSTIPS.PrintListActionsToolbar"





        Title="Print List">

        <UrlAction Url="{SiteUrl}/_layouts/PrintList.aspx?list={ListId}"/>




Almost done - install the feature and test it!

To install the feature, open command line (start>run>cmd) and navigate to the bin folder in the 12 hive.

Once there, run the following command to install the feature:

stsadm -o installfeature -name PrintListMenuAction -force

After you ran that command successfuly, you can activate the feature in the site collection either using the user interface (site actions> site settings> site collection features):

or you can (more easily since you are already in the command line) just run the following command, entering the site path:

stsadm -o activatefeature -name PrintListMenuAction -url [your site url here] -force

That's it! if you now go to any list in that site, you should have the print menu action.

Convert Word to PDF

I would highly recoomend ASPOSE.WORDS product to convert word documents into PDF in SharePoint.It is not a free product but is good for the functionality.

Branding Notes for SharePoint

I thought I would run through some of the tools that have helped me when branding a MOSS intranet. SharePoint Designer or perhaps better yet Studio can be the primary tool for creating master pages, themes, and page layouts, but your gonna need some help when trying to dig through all the CSS in the core.css file, and all it’s crazy inheritance. Combing through the css is a big chunk of your effort when you are starting with the default master or the default or classic theme. Most corporate organizations that I have worked with take the approach of “skinning” the SharePoint default look to match there colors and branding as opposed to starting from the ground up. So odds are your starting with the default look : -(

A couple of prerequisite tips before I get to the tools…..

When creating or modify styles - always, always, always put them in a new stylesheet. If you just update core.css, you will have a lot of pain in your life when your discover some goofy UI thing happening on a page, and you have to comb through the 4,000+ lines of styles in core.

Be cautious of overwriting or adding images directly in the _layouts/Images directory (C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\IMAGES) . If the box has to have MOSS reinstalled or perhaps some obscure patch occurs - you can kiss those image updates goodbye. However, I know that sometimes this is unavoidable….or at least a huge time saver. If your implementing a larger project, then put the images you added or modified in source control, and have a build script that will push the images. This way all the customization can be automatically pushed. OR if is a small implementation, at least document the image changes :- )

So…..oh yeah……The Tools:

IE Developer Toolbar

Certainly the biggest challenge in modifying the UI of MOSS is trying to figure out which style does what…and where is does it. And a good way to discover what MOSS is doing with it’s ginormous style sheet is to look at the rendered pages in the site. The IE Developer toolbar will provide 2 great features that will aid in this discovery process. 1. From the menu select ‘Find’ and ‘Select Element by Click’ which will allow you to click on any element in the page, and see the class used as well as all of the style attributes. So even if you see the class you modified, but say it is still show a incorrect style value (like color, padding, or whatever) then you know your style is being overwritten somewhere else. 2. As you select an element is also gives you a window with the html of the page that is much easier to comb though than viewing source in Notepad - That way you can crawl up and down the html tags to see what styles are being applied at the div, td, tr, table, etc. and……OK #3 - you can also disable scripts with a click so you can see styles without the hover state kicking in (i.e. - Menus)

CSS Finder Code (courtesy of msdn)

Similar to the IE Developer toolbar, you can throw this snippet into a content editor web part, which will allow you to roll over elements on the page and have the css style show up in a div tag on the screen. It is handy and quick, but will not give you as much information as the IE Developer toolbar. I would click on the link above because this page has a css reference chart that is fairly useful - also see Heather Solomon’s CSS Reference to get and idea for some of the major styles.

<script language="jscript">
function ClassInfo()
    if (window.event.srcElement.className != null)
        stsclass.innerText = window.event.srcElement.className;

        stsclass.innerText = "";

window.document.body.onmouseover = ClassInfo;</script>

<div style="border-style:solid;border-width:1px; width: 281px; height: 34px;
position: absolute; left: 286px; top: 41px; z-index:15; padding-left:4px;
padding-right:4px; padding-top:2px; padding-bottom:2px; background-color:#EEEEF4">
<p id="stsclasstitle"><font face="Tahoma" id="stsclasstitle">Classname: </font>

<font face="Tahoma"id="stsclass">&#xa0;</font>

Just Color Picker

Again another tool for style discovery (are you getting that this is a pain) I will use this little piece of freeware to quickly identify the hex color of an element on a page. Sometimes when you swear up and down that you have changed a color but it just wont show, I will get the hex off the screen, and start start seeing where that color shows up in the various style sheets.

SharePoint Skinner

This is a handy tool when you need to create a down and dirty theme - quickly. I’ll admit I have not played with this too much, but it will allow you so change colors and images with a few clicks, and export out a theme. This may also help you get an understanding of what css classes effect what styles, but I find the developer toolbar more efficient for that task.

Features and Deployment

The easiest way to deploy your look and feel to SharePoint is to utilize the Solution Framework MOSS provides. Especially in a farm environment where files need to be pushed to multiple servers. Features are also what I would recommend when including look and feel into site definitions. Many people have posted adding master pages to a Module Element in the ONET file of a site definition, but that will deploy a copy of the master page file to every site provisioned based on your definition. To me, this defeats the point of a template as it can not be globally changed now that you have copies stored in every web. You can create features that utilize receiver classes to programmatically apply a master page or theme when a feature is activated. You can also auto-activate these types of features in a custom site definition. Some good examples of how this is done are here:

Graham Sibley shows how to write a feature that deploys a theme to a site

Paul Papanek Stork shows how to write a feature that apply’s a master page to a site. This feature will apply a mater page from the /_catalogs directory at the root of the site collection.

Now that you are writing all these crazy features you may want a way to take some of the legwork out of the process. My friend Rich Finn has created a WSP Project Template for Visual Studio that will create the wsp along with the manifest.xml, and .ddf files for you. It also has deployment and upgrade scripts built in to deploy your look and feel to the portal. There is another one on CodePlex called SharePoint Feature Packager that will also do the trick, but Rich’s template has less manual steps to get rolling.

These tools definitely make life easier, but before implementing a portal look and feel, be sure to take all the proper planning steps to ensure that what you are implementing will best suit the long term needs of the business. SharePoint has made a lot of headway in how things can be packaged, deployed, and templated, but there are still a lot of gotchas - you don’t want to deploy a look and feel to a ton of pages and later find out something drastic has to change. You may find yourself rebuilding pages manually or basically undergoing a site migration. Each organization needs to consider things like:

Site Definitions vs. Site Templates

Themes vs. Masterpages - one or the other or both

Features and scope of those features

What meta data will be applied in our templates

Carefully document the pros and cons of each of these decisions so that the business can understand the potential impacts of the decisions being made during the design phase of a project.