h1

IsReusable on the IHttpHandler interface

November 1, 2007

I saw a recent interesting question about HttpHandlers on the ASP.NET forums that I wanted to share:

“What is the purpose of the IsReusable() method on the IHttpHandler interface?”

Well, to answer it we have to understand that a HttpHandler is processed as part of the request life cycle in ASP.NET and for every one of those requests an instance of the appropriate HttpHandler is required.

The IsReusable property enables you to indicate that the same instance can be pooled and used by concurrent requests.

This is useful when you have a lot of initialisation code occurring inside the handler that does not have to be repeated for every single worker thread and request.
For example:

public class MyHandler : IHttpHandler
{
public MyHandler()
{
//constructor logic involves
// a lot of processing and object instantiation
}

#region IHttpHandler Members
public void ProcessRequest(HttpContext context)
{
context.Response.Write(“biscuit”);
}

public bool IsReusable
{
get { return true; }
}
#endregion
}

This illustrates a simple example where the actual processing is writing some text to the context.

So why do we have to worry about whether it is true or false?

We need to make it Thread safe

If you are indicating that the HttpHandler can be re-used then it needs to be programmed with thread safety in mind.
Concurrent requests that can interfere with object state can cause havoc with the results of the handler’s use when it is not thread safe.

Here is an example:

public class MyHandler : IHttpHandler
{

protected
string exampleString;

public MyHandler()
{
//constructor logic involves
// a lot of processing and object instantiation
}

#region IHttpHandler Members
public void ProcessRequest(HttpContext context)
{
exampleString = MyUtility.FromUrl(context.Request.Url.ToString() );

context.Response.Write(exampleString);
}

public bool IsReusable
{
get { return true; }
}
#endregion
}

Between the two lines in the ProcessRequest method there is an opportunity for context switching to interfere with the processing of the handler.
If concurrent requests are using this handler, as one request has retrieved and set the exampleString variable based on url parameters a context switch to a second request thread at the same point means that exampleString is changed to a new value.
When processing switches back to the original request thread, it writes out a potentially different value than the one intended.
Ouch.

Such a problem would probably cause “intermittent” failures and a problem that was potentially hard to pin down.
So if in doubt about thread safety, set the IsReusable method to false.

Otherwise, if you are sure it is thread safe, set to true and pool the handler for potential increased performance in high volume environments.

h1

The Visual Studio 2005 Process Editor (WIT changes part 2)

October 29, 2007

In part one I discussed the value of the process editor and the installation of the Power Tools download.

In this second part I wanted to show the capabilities of the process editor itself.

Once the Power Tools are installed, Visual Studio 2005 has some new integrated menu options available.
When in Team Explorer the “Team” menu now has an extra option available for “Process Editor”:

Process Editor - Menu

The first item in the list facilitates opening and working on a local process template.
These process templates can be downloaded from the Team Server by using the existing “Process Template Manager” on the Team -> Team Foundation Server settings menu option.

The second menu item is the one used to make the changes on the work item and the options are:

  • Open WIT from server
  • Open WIT from file
  • Import WIT
  • Export WIT

This is where automation of the witexport and witimport command line process comes in -from the process editor I can now do all of my work item changes and upload them to the server project using this handy tool.

The third option is for Global Lists allowing storage of listitem values for the whole team to use on work item fields.
The options are the same as for WITs – open from server/file, import and export.

The final option to explore is the fourth in the list – Work Item Field Explorer.
With this I can connect to the server and explore all available fields, including the customised ones.

That’s it – a brief exploration of the process editor.
In the third part of this post series, I will look at making the changes and uploading them to the server.

h1

Firefox crash fixed with safe mode

October 23, 2007

Today my firefox crashed – opening it up produced an error message:
firefox.exe – Application Eror: The instruction at “0×0064c30c” referenced memory at “0×00000000″. The memory could not be “read”.
Ouch!
This prevented use of the browser completely:

Firefox error

After searching for a while on google for firefox crashes (through IE), I came across the safe mode of the firefox browser.

I simply clicked on Start–>Run and typed

firefox -safe-mode

This enabled me to start the browser with all add-ons and themes turned off and yes, it loaded ok.
So it appeared that one of my add-ons was broken.

With a little trial and error where I permanently disabled them and then enabled one-by-one until the next opening of firefox crashed, I discovered that the culprit was the Load Time Analzyer 1.5.
Not sure what the exact issue is, but I don’t need the add on so I disabled it.

So this post is just a quick tip… if you need to fix firefox there is an easy safe mode option available.

h1

Using Team Foundation Server Power Tools (WIT changes part 1)

October 22, 2007

Recently I’ve been customising work item templates in team foundation server – the company I am at have previously been using the CMMI process out-of-the-box but inevitably after some continued use the process now needs some changes and some work item adjusted.

I realise that some companies customise straight away – their processes are clearly defined and TFS needs to be implemented in a particular manner in order for the team to function correctly.
Our situation was less rigid, so it was decided to go with the standard process until it was felt that changes were needed.

Changing work item templates, when new to team foundation server seems quite daunting – the first things I needed to learn about changing the work item templates were the witimport and witexport commands – these allow the import and export of XML definitions for work items on an existing project via the command line and editing the xml by hand was fiddly to say the least.

But with the use of the Team Foundation Server Power Tools it is a relatively painless process and in the latest release, the Visual Studio Team System Process Editor saves the day – it enables a visual representation of the work item templates and processes and allows you to easily customise them, all integrated into Visual Studio.

Before I installed the power tool, I first had to check if I had the Domain-Specific Language Tools for Visual Studio 2005 Redistributable Components installed (what a mouth-full!) as this is a pre-requisite for the process editor.
I didn’t, so I downloaded and installed this first.

Now I was all set up and ready to go – time to make the changes!

In the second part I’ll be exploring the process editor capabilities and what we used to effect our changes.

h1

Ajax is the present, not the future

October 18, 2007

Ajax is great, but I think most experienced programmers recognise that it’s essentially nothing new.
The PS3 of client side callback scripting, it’s a nicely packaged and hugely hyped paradigm that still has advocates blue in the face from shouting about it and if it hasn’t already, it is coming to a requirements document near you soon.

Rockford Lhotka talks, in a Visual Studio Magazine guest column entitled “The web is dead”, about Ajax being the last dying breath of the web as we know it:

“I submit that AJAX is the last gasp of a dying technology. It is the hack that adds the straw that will break the camel’s back. Yes, AJAX is cool, and it allows some adequately rich interaction while retaining reasonably broad reach, but it also pushes the browser as far as we’re likely to go. Beyond this point, either the browser transforms into a full-blown programming platform or we find another answer.”

And he is spot on.

I think Ajax will be a long dying breath and it will last for some time – the good ajax sites will give rich, plentiful user experiences for some time to come and the web will be a better place for it.
The bad ones will just have rampantly Ajax-ed everything and, get this – as the user types.. the word suggestions come up.
Wow.
How did we ever live without it?

The future is already here – products like Silverlight and the Windows Presentation Foundation from Microsoft have got me converted already and I’m on my first steps to learning about them.
This rich bundle of technology seems to be the evolution of my .NET experience and I’m about to get on the Microsoft Silverlight bandwagon – having tinkered with flash some time ago, but with no success, I’m finding a viable alternative… in the langauge that I already know.
XAML.. now that’s a new one though. Where’s my Amazon bookmark?

Rockford plugs Silverlight in that same column (well, he would, he’s a Microsoft Regional Director).
And again I think he’s right.. for me anyway:

“The Web isn’t dead, but it is about to undergo the biggest transformation in the past decade. Given a choice between writing complex JavaScript that must accommodate differences in browsers to interact with an antiquated browser API, or writing C# or VB .NET code that is consistent regardless of browser or platform, and which uses a modern API, I think most developers would choose the latter, hands down.”

Looks like it’s new technology reading time again.

h1

Ensuring UI implementation with interfaces

October 16, 2007

I had recently been reading about the Model View Presenter design pattern and although I found it interesting, it didn’t quite fit the bill for my current client.
One of the main facets of the pattern is that it ensures the UI code is testable, especially in unit tests, but if you are not implementing full test-driven development the pattern seems like it could simply be an unnecessary layer.

Or so I thought until this week.
A situation presented itself this week that made me think that adapting the view model may be very beneficial for us.

We have two custom controls on a web page – one is a news article control that delivers news, picture, by lines (etc) and the other is a social bookmark control. Both are independent of each other so the bookmark control needs to have properties set from information in the article.

This is currently achieved by the page providing a delegate to the article control – when the article data is retrieved and the control populated, the event is raised to advise of the title (and other properties).
The page code behind then sets the bookmark control’s properties and fires a custom creation method for that control.
It all works great and we haven’t had any problems so far.

What suddenly clicked with me this week though is that there was something not right about the property assignment process… the code was fine and is illustrated below, but somehow something was up!

bookmarks.BookmarkTitle = title;
bookmarks.BookmarkUri = new System.Uri(url);
bookmarks.BookmarkGeneratorID = articleID;
bookmarks.BookmarkGeneratorType = GeneratorType.Article;
bookmarks.CreateCustom();

Again, the problem we have is not with the code itself, but with the enforcing of its implementation.
All of these properties have to be set in the bookmark control for it to be valid – an application exception is raised if they are missing or incorrect and again this is fine.
However, if I or another developer goes to implement the bookmark control in another of our websites the only way we know if all the properties are being set as they should be is that a run-time exception will be generated during testing.

Hmmm. This seems very loose – how can we enforce the assignment of these properties through design so that at compile-time we can see the error of our ways?
(note: this control must be declared in the aspx page, so we cannot create a new constructor, the default one is used by .NET in the HttpHandler when it creates the controls.)

Well, we could provide just the one method on the bookmark control that assigns the properties, but this doesn’t seem right either.

This is when I thought back to the model view presenter – if we can define a viewer interface we can force the page (viewer) to implement certain contracted properties and methods and this ensures that each is actioned and implemented.
Of course this can’t stop foolish implementation such as simple”return true;” code in the methods but it does force the developer to do something.

Here is a quick example I’ve rumbled up for this post:

public interface IBookmarkViewer
{
string BookmarkTitle { get; }
System.Uri BookmarkUri { get; }
int BookmarkGeneratorID { get; }
GeneratorType BookmarkGeneratorType { get; }
}

Here we are forcing the viewer to implement these properties and here is an example of what the page might be like in action as a “viewer”:

public class articlepage: BiscuitBasePageClass, IBookmarkViewer
{
public string BookmarkTitle {
get { return _title; }
}

public System.Uri BookmarkUri {
get { return _uri; }

etc

The rest of the implementation can be derived from the actual model view presenter pattern – here I am simply sounding out an idea in the post and have not written or tried to implement this.
Has anyone else implemented something similar, like a “slim” version of that pattern as illustrated above?

Note: the author of the pattern, Martin Fowler, has changed the original pattern and split it into two distinct ones- you can view his description of that here.

h1

Custom web.config settings

October 11, 2007

Most application settings inside a Web.config file can be created inside the <appsettings> section – a collection of name/value pair settings can serve many purposes such as mailserver settings, email settings and on/off flags for certain application functions.

Sometimes more complicated setting requirements involve the need for more than simple name and value pairs and here I will illustrate how to create custom settings in the web.config file.

I’m going to use a simplified version of a recent real example to illustrate this – a syndication feed setting that was required in a recent application we built.
The requirements were for a number of custom settings to identify:

  • a distinctive url pattern that corresponds to a particular feed
    (e.g. /news/ )
  • what class to use to process this feed at run-time
    (utilising dynamic instantiation using reflection)
  • a name to describe the feed

In order to fulfill the requirement are going to do the following:

  1. Create a custom configuration section entry in the web.config file
  2. Input the section declaration itself and the actual settings
  3. Create a section handler class to parse the settings
  4. Create a class that will represent each individual setting
  5. Encapsulate the read of the config section

1. Creating the custom section

A custom section can be created inside the <configSections> node of the web.config file and we declare the name and type which represents the class that handles the section.
In our example, the web.config custom section looks like this:

<configSections>  

<section name="SyndicationFeeds" _
    type="Biscuit.SyndicationFeedsSectionHandler, Biscuit" />  

</configSections>

Here we are creating a section called SyndicationFeeds and we are instructing that the section handler to use is the SyndicationFeedsSectionHandler class in the Biscuit assembly.

2. The section declaration

The next step is the declaration of the section itself and because this is all about customisation, you can describe this section as you see fit.
In our example the actual section declaration looks like this:

<SyndicationFeeds>  

 <Feed Name="Test" Pattern="*/test/*" _
    Class="Biscuit.Feeds.TestFeed" Assembly="Biscuit"/>  

 <Feed Name="Article" Pattern="*/news/*" _
    Class="Biscuit.Feeds.NewsFeed" Assembly="Biscuit"/>  

 <Feed Name="Comment" Pattern="*/comments/*" _
    Class="Biscuit.Feeds.CommentFeed" Assembly="Biscuit"/>  

</SyndicationFeeds>

Here we are declaring three settings and each have the following attributes:

  • Name
  • Pattern
  • Class
  • Assembly

3. The section handler class

The class used to handle the custom config section needs to implement the IConfigurationSectionHandler interface which requires a Create method that is called when the section is read:

public object Create(object parent, object configContext, _
       System.Xml.XmlNode section)

Using the Xml object passed into the method, our custom code can parse each node of section and read the attributes and create objects based on them:

public object Create(object parent, object configContext, _
     System.Xml.XmlNode section)
{
    foreach(XmlNode feed in section.ChildNodes)
    {
       //do something
    }
    return xxxxx;
}

4. The setting class

We now want to create a class that can represent the values of the setting and we can do so with properties on the class for each attribute of the setting we declared in step 2:


public class SyndicationFeedSetting
{
   private string _name;
   public string Name
   {
      get { return _name; }
   }

   private string _pattern;
   public string Pattern
   {
      get { return _pattern;}
   }

   private string _class;
   public string Class
   {
      get { return _class; }
   }

   private string _assembly;
   public string Assembly
   {
      get { return _assembly; }
   }

   // Constructor
   public SyndicationFeedSetting(string name, _
   string pattern, string className, string assembly)
   {
      _name = name;
      _pattern = pattern;
      _class = className;
      _assembly = assembly;
   }
}

We can now fill in the blanks in our section handler so that as the nodes are parsed we create a list of these setting classes:

public object Create(object parent, object configContext, _
       System.Xml.XmlNode section)
{
   ArrayList feedList = new ArrayList();  

  foreach(XmlNode feed in section.ChildNodes)
    {
       feedList.Add(new SyndicationFeedSetting( _
              feed.Attributes["Name"].Value, _
              feed.Attributes["Pattern"].Value, _
              feed.Attributes["Class"].Value, _
              feed.Attributes["Assembly"].Value) );
    }  

    return feedList;
}

(Note: this is 1.1 code that we were using. I have not demonstrated here, but in 2.0 you could return a generic List<T> with type of SyndicationFeedSetting).

5. Encapsulate the read of the config section

It is my suggestion that you also encapsulate the reading of the section from the web.config file. This is especially relevant if you are using in multiple areas in your code as typing the following in multiple places is a bit messy:

System.Configuration.ConfigurationSettings.GetConfig(“SyndicationFeeds”);

Having this declaration in multiple areas complicates the process of future improvements or changes to the code.
By wrapping the retrieval inside another class you can have one point of change.


public class SyndicationConfigurationManager
{
    private SyndicationConfigurationManager()
   {
      //no construction allowed.
    }  

    public static ArrayList GetFeeds()
   {
      return (ArrayList)System.Configuration._
       ConfigurationSettings.GetConfig("SyndicationFeeds");
    }
}

Using the code and further Improvements

To use the above, in your code you now retrieve the settings (as an ArrayList currently, but see below for improvements) with a simple call to:


ArrayList feeds = SyndicationConfigurationManager.GetFeeds();

The above samples of code can be further improved in certain areas and has been written here to be purposefully compact.
For example, there is no error checking of the parameters in the handler class and more importantly the SyndicationFeedSetting class itself (on constructor parameters).

You can also change the SyndicationFeedManager class so that it returns an array of SyndicationFeedSettings as opposed to an ArrayList making it more type-safe at compile time.
As mentioned earlier, in 2.0 you can achieve this with a generic List being returned in both cases.

h1

Branching in source control musings

October 5, 2007

Every week I’ll be looking to share a particular topic that I’ve been thinking about usually based on a post from an interesting blog or article.

This week, the post that got me thinking the most was one on the coding horror blog entitled Software Branching and Parallel Universes.

In the current environment I’m working in there is no branching involved – all code is developed in the same common code and exclusive checkouts are used to ensure that no cross-over or interference occurs. This limits the opportunity for parallel development, but to be honest that isn’t really a factor with so many products for us to maintain at any one time – that is probably the defining factor in the lack of branching use.

That’s not to say it hasn’t been discussed and that initial discussions haven’t taken place on it. Unfortunately most of these discussions haven’t evolved into anything concrete, but perhaps the Coding Horror post will spark something into life for us.

Branch per Task
Every development task is a new, independent branch. Tasks are merged into the permanent main branch as they are completed.

This is probably the most appropriate to my current environment – we have internal web site projects (many of them!) that don’t really version… they get enhanced as new functionality is plugged in or change requests are developed and implemented.

A task orientated approach may prove very useful but it brings back questions that we have faltered on before (and effectively given up on).
Say we have a website – websiteA – and this has 5 common core class library projects that it shares with up to 10 other sites. A change request may result in a branch being created for websiteA-Change1045 (as an example) and this can be worked on in isolation.
However, invariably some changes require the common code to be improved upon in some way and here we will also have to branch each and every component library we wish to modify. Without a clear branching strategy we can see that this could get ugly.. especially as simply typing inside a file in VS2005 automatically checks out the file behind the scenes with no confirmation request.. this would be very easy to do on the existing “release/original” code for those libraries in source control.

I guess it is all about thinking ahead with that clear branching strategy and also what advantages this gives to the build features of Team Foundation Server that we currently use.
At present we cannot build to a UAT environment automatically due to the nature of the check-ins happening on the common code (they often occur post-development but pre-full integration testing).

On a lighter note, the post also suggests thinking about branching in terms of parallel universes:

Perhaps the most accessible way to think of branches is as parallel universes. They’re places where, for whatever reason, history didn’t go quite the same way as it did in your universe. From that point forward, that universe can be slightly different– or it can be radically and utterly transformed.

One of the recent definitive parallel universes is the Star Wars Infinities series from Dark Horse Comics.
It is silliness in a world that is revered by many and is a recommended read if not solely for it’s boldness in taking on the canon pedants.

h1

Undo a check out in Team Foundation Server source control

October 3, 2007

Almost every team that uses source control will inevitably find themeselves in a situation where a file is checked out and locked and needs to become available for someone to work on it. Often the person who has the file checked out is currently on holiday or has left the company or, as with our recent situation, the original machine used for the check out no longer exists.

In Team Foundation Server source control, the workspace is a local copy of the files on the server and this copy is isolated from any other changes that may occur on the files. You can in fact have multiple workspaces across different machines – something that happens frequently for contractors who hot-desk.
If one of these machines is rebuilt or simply dies, the original workspace relationship on the check out in source control remains and the file can never be checked in.

So how do you undo a check out?
First, you must have administation priviliges; secondly, if you are not in a domain-controlled environment (as is our situation) you have to be on the team foundation server itself.

Using the Visual Studio 2005 Command Prompt, you can make use of the TF command-line utility to issue a command to undo or unlock the check out.

In our experience, the Undo Command was the operation best served to reverse the check out and lock actions as this “removes pending changes from a workspace”:

TF UNDO $filepath$ /Workspace:$workspace$;$user$ /s:$server$

e.g. TF UNDO $/MyProject/Folder1/File1.cs
        /Workspace:MX4545;john.smith /s:http://myteamserver:8080

Note that you must specify the workspace and user that you wish to reverse actions for – if you are unsure of the current workspace that the file is checked out under, simply go into your source control and attempt to check the file out.
You will receive a warning informing you of the user and workspace the file is checked out to.

Note that when you run this command successfully what appears to be a yellow error comes up in the command window:
“The workspace MX4545;john.smith is not on this computer. Run get (get all if edits were undone) on the computer hosting that workspace to update it with the changes that have been made on the server.”
This is infact showing you that it was successful but the files for that workspace/user require a get latest to become up to date with your undo changes you have made.

An alternative method to unlock the file is the Lock Command:

TF LOCK $filepath$ /lock:none /Workspace:$workspace$;$user$ /s:$server$

… but we found this problematic due to the following note in the msdn documentation:

Having the Unlock other user’s changes permission set to Allow is required to remove a lock held by another user if you do not have Write permission for that user’s workspace.

One other handy command related to this is the Status Command with which you can obtain a list of all files checked out to a particular user – particlarly useful when a user no longer exists and you need to undo all files checked out by that individual.

h1

Dynamic instantiation using reflection

October 1, 2007

I’ll first introduce you to a problem we recently had that required the dynamic provision of a class for a particular task and then discuss how we came to solve it using the reflection method Assembly.CreateInstance().

The background
We have many websites – well into double figures – that all utilise a common exception monitoring HttpModule that we wrote. This module is very pluggable and can also be used by third party sites that we either host or assist with developing.

The ExceptionModule, on a basic level does the following:

  • In the Init() method subscribes to the HttpApplication.Error event
  • Once the error is caught, logs the exception details (in database, event log, xml file depending on setting)
  • Looks to transfer the request to a “landing page”- obtained from web.config setting

This landing page reports a branded apology to the end user for browsers and changes the HttpResponse header so that an appropriate Http Header is sent to the client.

Note: this navigation was done using Server.Transfer() so as not to redirect the browser in any way – it receives a branded page and Http Response for the original request (if you need more information on this, let me know and I can blog in detail about it).

The design problem
The original coding of this module was fine and the application worked as intended. However, soon after being rolled out on many sites we came across a design problem when implementing in one particular site caused by how it was set up.

The site is “split” into two distinct halves of functionality – when there is an error in one half, the exception module needs to transfer to one particular branded “landing” page; if an error occurs on the other half, the module needs to transfer to a different page.

In our original design, this wasn’t accounted for and the landing page was obtained from a name/value pair in the web.config file:
<add key=”HttpLandingPage” value=”landing.aspx” />

The challenges

  • How can we instead have two different parameters for this transfer mechanism?
  • How can the exception monitor/module be sure of the logic of the decision in which “half” of that site it needs to transfer to? It definitely should not sit in this shared utility.
  • If we make it database driven, how do we introduce business logic based on the site location?
  • Have rules without hardcoding them in mother-of-all class with logic based on which site it is in? (e.g. a switch statement where each “case x:” is the site)

Our solution was to enable the site itself to suggest where the landing page should be and be able to decide on the business logic – by providing the ability to customise this whole process, we can make this dynamic.
So how did we do this?

The web.config setting
We changed the web.config setting so that it now provides the assembly name and the class/type that will provide the landing page information (namespace and assembly below is false!):

<add key=”LandingPageProvider”
value=”Biscuit.Landing.GenericLandingPageProvider, BiscuitClasses” />

The ILandingProvider interface
We then defined a simple Interface that classes could implement to provide the landing information to the module code:

public interface ILandingPageProvider
{
   string GetLandingPage(HttpContext context);
}

We also created a generic provider for use in most situations:

public class GenericLandingPageProvider : ILandingPageProvider
{
   public GenericLandingPageProvider()
   {	//no constructor required   }

      public string GetLandingPage(HttpContext context)
   {
      return "landing.aspx";
   }
}

Dynamic Instantiation
The climax of this solution is how we instantiate this string that is in the web.config file and implement this on the fly.
To do this we created a utility class that reads the web.config (using custom ConfigItems not explored here) and creates an instance of the object at run-time:

public class LandingPageUtility
{
   private LandingPageUtility()
   {  // no constructor required - private so cannot instantiate   }

   public static ILandingPageProvider GetLandingPageProvider()
   {
      ILandingPageProvider provider = null;

      string configProvider = ConfigItems.Get("LandingPageProvider");

      if(configProvider.IndexOf(",")>0)
      {
         // Retrieve the assembly and class
         string assemblyName = configProvider.Substring( _
                                 configProvider.IndexOf(",")+1).Trim();
         string className = configProvider.Substring( _
                                 0, configProvider.IndexOf(",")).Trim();

         // create an instance of the class from the assembly
         System.Reflection.Assembly assembly = _
                              System.Reflection.Assembly.Load(assemblyName);
         object o = assembly.CreateInstance(className);

         // check if this class implements ILandingPageProvider interface
         if(o is ILandingPageProvider)
             provider = (ILandingPageProvider)o;
      }

      return provider;
   }
}

The most important parts in the code above are the two lines in the centre of the if statement – we first load the assembly from the web.config setting giving us an instantiated Assembly object and then call the Assembly.CreateInstance() method upon it.
This reflection method uses the System.Activator class to instantiate the type specified by string provided and enables us to achieve our dynamic instantation from the web.config file.
We receive an instantiated object type and then check for the interface implementation before casting.
(Note: this procedure purposefully returns null if the config is set up incorrectly as we know it is specifically consumed by the exception monitor that will already be in the process of handling an exception, so we do not throw another.)

Using the provider
The HttpModule pulls all of this together when it wants to call the Server.Transfer() method.
To retrieve the landing page it does the following:

ILandingPageProvider provider = LandingPageUtility.GetLandingPageProvider();

context.Server.Transfer(provider.GetLandingStaticPage(context) );

In summary
We have enabled the dynamic provision of a landing page and expanded our original design past the limiting one-page provider scenario.
This may (to some) seem like overkill for what is effectively one string, but we have in fact only created one interface, a generic provider class and utility class to instantiate the web.config setting.

What we have done though is enable business logic to be provided on a site-by-site basis – by creating a new class that implements the ILandingPageProvider class we can have simple or complicated code that decides on where the exception module transfer mechanism goes to. We have also future-proofed this for third-party partners who may have more complicated requirements such as our “split” site.

Our solution in the “split” site itself was then to create a custom class that used the HttpContext object that was passed in to retrieve the Request.Url and apply certain rules to decide which page to provide as the landing page.