http://www.developer.com/

Back to article

Extend the Flexibility and Functionality of SharePoint with HTTP Modules and Handlers


March 27, 2009

From its creation, developers recognized Hypertext Markup Language's restriction of only allowing the creation of static content as a problem that placed limitations on the rapidly expanding area of Web technology. Developers wanted a way to add dynamics to applications; to render content from a database or to accept interaction with users. To achieve this goal, companies creating servers devised complementary technologies to allow for dynamic use of the Internet. Microsoft presented the Internet Server API (ISAPI) for its Internet Information Services (IIS) — also adopted by Apache — and Netscape developed NSAPI (Netscape Server API) for the same purpose.

ISAPI consists of two principal parts, Extensions and Filters. Extensions are 'standard' applications that run from a Web request. The best known ISAPI Extension is the 'QueryString' that appears at the end of an URL in the form of an interrogation sign with at least one parameter, with each parameter separated by '&'(Forexample,http://Server/default.aspx?paremeter1=value1&parameter2=value2). Filters are, as the term implies, elements that distillate and modify the information between the request and the response from the Web

Programming the ISAPI has never been a simple matter. The technology is very complex, the developer must work directly with the assemblies from Win32, and because traditionally, it has only been possible using C/C++. As an alternative, ASP.NET introduced HttpHandlers and HttpModules.

HttpHandlers can be seen as the equivalent of ISAPI Extensions—components that implement the System.Web.IHttpHandler interface. The main difference with ISAPI Extensions is that HttpHandlers can directly instantiate files with any type of extension (normally .ashx)

In a similar way, HttpModules can be compared with ISAPI Filters in that they implement the System.Web.IHttpModule interface

The internal working of SharePoint 2003 was based entirely on an ISAPI Filter especially designed to manage the routing of Web requests. One of the collateral effects was that the complete IIS service was 'kidnapped' by SharePoint, blocking the working of other Web applications in the same server.

In SharePoint 2007, the ISAPI Filter was replaced by HttpHandlers and HttpModules, granting compatibility with ASP.NET and freeing the IIS service. Other advantages are that the new modules can be created to address specific tasks in the Portal and may be programmed with C# or Visual Basic.

HttpHandlers for SharePoint 2007

To construct a HttpHandler for SharePoint 2007 begin by creating a new file with the extension .ashx in the directory 'C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12TEMPLATELAYOUTS'. The following code writes text to the screen, based on the context of the Web page (code is based on a presentation by Ted Pattison):

<%@ WebHandler Language='C#' Class='HelloHttpHandler' %>
<%@ Assembly Name='Microsoft.SharePoint, Version=12.0.0.0, 
             Culture=neutral, PublicKeyToken=71e9bce111e9429c' %> 
using System;
using System.Web;
using Microsoft.SharePoint;
 
public class HelloHttpHandler : IHttpHandler 
{
  public bool IsReusable 
  {
    get { return false; }
  }
 
  public void ProcessRequest(HttpContext context) 
  {
    SPWeb myWeb = SPContext.Current.Web;
    context.Response.ContentType = 'text/plain';
context.Response.Write('Hello HttpHandler from the site ' +
       myWeb.Title + ' and ' + myWeb.Url);   
  }
}

After the references are set to the SharePoint assembly and the inheritance of the IHttpHandler interface, the code creates an instance of the property 'IsReusable' that it is obligatory for using the interface. Finally, in the 'ProcessRequest' method, a SPWeb object is created based in the context and an information text is fashioned. The method receives the 'HttpContext' as page parameter in such a way that the 'Response' method can be used to write directly to the screen.

This is a very straightforward, simplified example, but it is helpful to explain how a HttpHandler works. The type of response to write ('ContentType') is 'text/plain' in the example, but it is possible to use any recognized .NET type, such as XML, binaries (pictures, for example), PDFs and all Office documents. The extension .ashx is, by default, recognized by IIS as a HttpHandler, but any extension may be used if it is registered in the 'HttpHandlers' section of the web.config or machine.config files.

SharePoint takes care of the on-the-fly compilation of the code, and it is not necessary to install a dll. The file is not saved in memory, and an iisreset is unnecessary after modifying the code. The example can also be realized using traditional aspx pages, but the advantage of HttpHandlers resides in the possibility of choosing extensions in IIS that can be interpreted and displayed on screen using any type of transformation (contained in the 'ContentType' property). In this way it is possible to show a document such as a PDF directly in a navigator such as Internet Explorer, allowing for all type of content not predefined by default.

HttpModules for SharePoint 2007

HttpModules allow for the implementation of richer methods than HttpHandlers. The former permits implementing 'IsReusable' and 'ProcessRequest', as explained, but HttpModules can utilize different types of events such as 'AcquireRequestState', 'AuthenticateRequest' and 'AuthorizeRequest', and most importantly, 'Begin/EndRequest'. Another fundamental difference between modules and handlers is that the latter execute in any type of request, regardless of the file extension: this opens the door to create code that always works in the system, whether or not the page or request is sent to the server.

To use HttpModules in SharePoint, as mentioned, the most common events are 'BeginRequest' and 'EndRequest'. These two events allow catching the request before SharePoint processes it and after the response was processed but before it is sent to the client.

The most basic example of a HttpModule is one that eliminates all the responses in the system. In reality this is not practical, its usefulness is that it can be modified to, for example, create a message page if the Portal is in maintenance. Remember that the module executes in all requests, so that regardless of the URL used, the response is always the maintenance page. The source code for the module might look like this:

using System;
using System.Web;
 
namespace HttpModule_01
{
    public class Class1 : IHttpModule
    {
        public void Init(HttpApplication context) 
        { 
           context.BeginRequest += new EventHandler(BeginRequest); 
        } 
 
        private void BeginRequest(object sender, EventArgs e) 
        {
           HttpContext.Current.Server.Transfer(
                         "/_layouts/maintenance.html", false);
        } 
 
        public void Dispose() 
        { 
            // TODO:  Add Implementation of CustomModule.Dispose 
        }
    }
}

As you can see the real code consists of only two lines: in the initialization event is a reference to the method 'BeginRequest' and inside the routine, a code line that makes the request transfer to a maintenance page. The class inherits from the IHttpModule interface and a reference to 'System.Web' is required. The 'Dispose' method is obligatory for implementation and as a good programming rule, the method deletes the created and unused objects.

The project is realized in Visual Studio as a 'Class Library' and the assembly needs to be signed with a secure name. After compilation, the DLL can be copied to the bin directory of the respective Web application in the root of IIS (C:InetpubwwwrootwssVirtualDirectories80bin, for example). The assembly may also be installed in the GAC, but to restrict its scope to a specific Web application it is recommended to install it in the Bin directory. To ensure that SharePoint acknowledges the module, the next code lines are added in the 'web.config' file of the Web Application in IIS, under the 'HttpModules' section:

<add name='HttpModule_01' type='HttpModule_01.Class1, HttpModule_01, 
     Version=1.0.0.0, Culture=neutral, PublicKeyToken=97bc1af85e70ceb9' />

Replace the correct values for name, type and KeyToken. As you can see in the 'HttpModules' section of the 'web.config' file, SharePoint has some modules already configured by default: cache, authentication, authorization and roles management. The order of the statements in the section is very important: authentication before authorization, and both before roles assignment; the order must be preserved to eliminate any disruption to the internal working of SharePoint. Normally if you create your own module, it is registered at the end of the section to prevent alterations to the system, however this is not obligatory: in the case of the maintenance page, it is possible that the module is registered at the beginning, because authentication and authorizations are unnecessary.

A typical utilization of the 'AfterRequest' event is to modify the response of SharePoint and display information in each page of the Portal, for example, a footnote pertaining to 'Conditions of Disclaimer':

using System;
using System.Web;
 
namespace HttpModule_02
{
    public class Class1 : IHttpModule
    {
        public void Init(HttpApplication context) 
        { 
           context.EndRequest += new EventHandler(EndRequest); 
        } 
 
        private void EndRequest(object sender, EventArgs e) 
        {
            HttpApplication myHttp = (HttpApplication) sender;
            myHttp.Context.Response.WriteSubstitution(
                new HttpResponseSubstitutionCallback(WriteText));
        }
 
        static protected string WriteText(HttpContext context)
        {
            return 'This is a disclaimer';
        }
 
        public void Dispose() 
        { 
            // TODO:  Add Implementation of CustomModule.Dispose 
        }
    }
}

In this case the 'EndRequest' event is initiated to modify the complete response. The 'EndRequest' method creates an object containing the response and calls a delegate method ('WriteText') using the 'WriteSubstitution' method that creates the text.

Note that the text appears after the '</body></html>' section in the HTML code. This does not create problems for a disclaimer or footnote because the result is expected and modern HTML navigators can render it without problem, however the code does not satisfy the w3.org specifications. A solution might be to save the complete HTML response temporarily in a binary stream, modify it using concatenation or a regular expression, remove the original result and send the modified stream. The purpose of the example is to show the use of modules in SharePoint, the implementation details are added following individual specifications. Also take care to save the disclaimer text outside the module source code otherwise if there are changes to the text, the code must be altered, compiled and installed again.

Although the most common events used with SharePoint are 'BeginRequest' and 'EndRequest', there are other ones designed to realize requirements. For example, to change a Master Page dynamically, the event 'PreRequestHandlerExecute' is used because it initiates precisely before the ASP.NET framework starts to execute the page; if you use a different event, the Master Page is already mixed with the content and it is impossible to change the generated HTML code. One possible source code to make this change is:

using System;
using System.Web;
using System.Web.UI;
 
namespace HttpModule_03
{
    public class Class1 : IHttpModule
    {
        public void Init(HttpApplication context) 
        { 
            context.PreRequestHandlerExecute += new EventHandler(ChangeRequest); 
        } 
 
        private void ChangeRequest(object sender, EventArgs e) 
        {
            Page myPage = HttpContext.Current.CurrentHandler as Page;
            if (myPage != null)
                myPage.MasterPageFile = '~/Master1.master';
        }
 
        public void Dispose()
        {
            // TODO:  Add Implementation for CustomModule.Dispose 
        }
    }
}

The possibilities of this module are extensive. In a default implementation, SharePoint allows defining only one Master Page for each Site Collection, and it is configured in the same way for all users in the Collection. 'Themes' is a method to ensure personalization in the Collection pages and allows for personal configurations, however the changes are limited to modifications in the CSS styles. With this module it is possible to modify pages based in user groups, including individual users; it also allows each user to have their own interface.

Continuing with the examples, a convenient HttpModule that can improve the user experience is the creation of a page with improved error information. By default, SharePoint displays a page indicating an error occurred, but does not provide additional information. A module can intercept the requests through IIS and capture errors:

using System;
using System.Diagnostics;
using System.Web;
 
namespace HttpModule_04
{
    public class Class1 : IHttpModule
    {
        public void Init(HttpApplication context) 
        { 
            context.Error += new EventHandler(MyError); 
        } 
 
        private void MyError(object sender, EventArgs e) 
        {
            Exception[] AllMyErrors = HttpContext.Current.AllErrors;
 
            foreach (Exception ex in AllMyErrors)
            {
                EventLog myLog = new EventLog();
                myLog.Log = 'Application';
                myLog.Source = 'My HttpModule';
               myLog.WriteEntry('An error has occurred');
            }
 

           HttpContext.Current.Server.ClearError();
           HttpContext.Current.Server.Transfer('/_layouts/MyErrorPage.aspx');
        } 
 
        public void Dispose() 
        { 
            // TODO:  Add Implementation of CustomModule.Dispose 
        }
    }
}

The 'Error' event in the module executes the 'MyError' routine that makes an array of exceptions. Each error in the array is examined to make an entry in the Windows Log Viewer. Finally the errors in the context are eliminated and a redirection to the error pages is implemented. This page displays the error type and a message indicating the steps to follow. The message used in the code is simple but it may contain the required information. In a similar way, errors can be saved to an external system (database or SharePoint List) and complementary actions taken, such as send an email to the system administrator.

Conclusions

HttpHandlers and HttpModules allow developers to extend the flexibility and functionality of SharePoint. Developers have been slow in recognizing their possibilities so they have not been used extensively. Hopefully this will change. HttpHandlers and HttpModules are easy to program and can be widely implemented in the system, so they are a useful tool to add to the SharePoint developer's toolbox.

The author

Gustavo Velez is a Manager in the Solutions Development department at Avanade Netherlands, a global consultancy company. He has many years experience developing Windows and Office applications, and more than six years of daily programming experience with SharePoint. The author's articles can be found in many of the leading trade magazines in English, Dutch and Spanish. He is also pleased to be Webmaster of http://www.gavd.net, the only Spanish-language site dedicated to SharePoint. Spanish-language readers may want to consult Velez's book, Programación con SharePoint 2007. In March, Gustavo's English-language book on Workflows is scheduled for publication. Velez has been awarded MVP status in the area of SharePoint MOSS.

Sitemap | Contact Us

Thanks for your registration, follow us on our social networks to keep up-to-date