The ASP.NET Singleton-per-Request pattern

Lately I needed to have an instance of a class to be unique for a certain amount of time, that is, one instance only of that class should exist for that time interval in my app domain.
In these cases what comes to my mind is the Singleton Design Pattern, which imposes that one instance only of a class can be loaded into an app domain and is alive as long as the app domain is.
My problem was that I needed that object to be unique only for a small time interval, which later I identified as being the life of a single request. That's when I recalled of a very useful IDictionary collection whose lifetime corresponds to the request-response cycle, and where you can store items which are then available during all the stages of the pipeline. This object is the Items instance property of the HttpContext class, and is defined as following:
System.Collections.IDictionary HttpContext.Items
Let me say it again: into this collection you can store items that are then made available during all the request-response process, and are unique to that particular request-response. To enfore this and make it even clearer, the description of this object as given by the intellisense is:

Gets a key/value collection that can be used to organize and share data between
an System.Web.IHttpModule interface and an System.Web.IHttpHandler interface
during an HTTP request.


You understand how powerful this object is, and the ASP.NET engine uses this mechanism itself to mantain some state information, like the session id and something more.
Going back to my problem, what I wanted to achieve is a lazy load (created only when necessary) instance of a class being unique to my request, so I came up with this code.
public class SingletonPerRequest
{
public static SingletonPerRequest Current
{
get
{
return (HttpContext.Current.Items["SingletonPerRequest"] ??
(HttpContext.Current.Items["SingletonPerRequest"] =
new SingletonPerRequest())) as SingletonPerRequest;

}
}
}
which can be used calling the static Current property of the class. What this code does is check if an instance of the class is already in the Items collection. In that case, it returns a reference to that instance, otherwise a new instance is created and placed in the Items collection, so that the next time it is requested during this same request it's already there.
Note that here we don't need any synchronization mechanism, since a single request is not executed concurrently by more than one thread.

kick it on DotNetKicks.com

Published 21 August 2006 09:58 AM by simoneb
Filed under: ,

Comments

# DotNetKicks.com said on 21 August, 2006 02:10 AM
You've been kicked (a good thing) - Trackback from DotNetKicks.com
# Billy said on 21 August, 2006 03:07 PM
I'd recommend using System.Runtime.Remoting.Messaging.CallContext.GetData and CallContext.SetData instead, they perform the exact same functionality as HttpContext.Current.Items, but CallContext.Get/Set is portable between Web and Windows apps.  (In fact, HttpContext.Current.Items uses CallContext under the covers but binds you to a web env't.)  A real-world example of when the Windows/Web portability is useful is in an NHibernate session utility which stores/retrieves an ISession in the context.

Billy
# simoneb said on 21 August, 2006 03:19 PM
Thanks Billy for pointing that out. I didn't know about it at all, maybe because I don't use to develop desktop applications, but it's an interesting point. Let me thank you for your great latest article on codeproject, I read it a few days ago and found it very well written and interesting. Keep up the good work.
# RossCode.com - The Singleton Pattern, ASP.NET, And More... said on 05 September, 2006 11:18 PM

PingBack from http://www.rosscode.com/blog/index.php?title=the_singleton_pattern_asp_net_and_more&more=1&c=1&tb=1&pb=1

# Walter said on 10 September, 2006 02:29 PM
You need to pay more carefullness when using CallContext. First,HttpContext is not strightly use CallContext, it use CallContext.HostContext and there is Context switching concept (implemented in System.Web.Hosting.ContextBase ) because of multi-threading implementation in asp.net. So for web, I think it's the best situation to use httpContext instead of CallContext.
# Blog-a-Styx said on 22 September, 2006 06:48 AM

Une nouvelle découverte dans les specs du langage c# : l'opérateur ?? . Je connaissais l'opérateur ?:

# George Polevoy said on 01 November, 2006 02:37 PM

My strongly typed generic singletons

using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;

namespace Variatron
{
    public abstract class ContextSingletonBase<T>
    {
        public T subject
        {
            get { return (T)CallContext.GetData(key); }
            set { CallContext.SetData(key, value); }
        }

        abstract protected string key
        {
            get;
        }
    }
}

public class ContextSingletonExample : Variatron.ContextSingletonBase<Decimal>
{
    protected override string key { get { return "Me single too"; } }
}

[Test]
public void CurrentContext_()
{
    Decimal one = 1;
    ContextSingletonExample accessor = new ContextSingletonExample();

    accessor.subject = one;

    Decimal number = accessor.subject;

    Assert.AreEqual(one, number);
}

public class ContextSingletonGoodExample : Variatron.ContextSingletonBase<Decimal>
{
    protected override string key { get { return "So lonely singleton"; } }

    protected ContextSingletonGoodExample(){}

    private static ContextSingletonGoodExample _i = new ContextSingletonGoodExample();

    public static Decimal Current
    {
        get { return _i.subject; } set { _i.subject = value; }
    }
}

[Test]
public void ContextSingleton_good_test()
{
    Decimal one = 1;
    ContextSingletonGoodExample.Current = one;

    Assert.AreEqual(one, ContextSingletonGoodExample.Current);
}

# Speednet said on 18 December, 2006 04:32 PM
Simone, This is a terrific blog entry on a topic that most people don't give enough attention. George, That ContextSingletonBase class is very nice, I'll be using it. However, since my development is done in VB, I'll post my VB.NET translation: Imports System.Collections.Generic Imports System.Runtime.Remoting.Messaging Namespace Speednet Public MustInherit Class ContextSingletonBase(Of T) Public Property Subject() As T Get Return CType(CallContext.GetData(Key), T) End Get Set(ByVal value As T) CallContext.SetData(Key, value) End Set End Property Protected MustOverride ReadOnly Property Key() As String End Class End Namespace
# SimoneB's Blog said on 16 April, 2007 08:11 PM

A while ago I blogged about a pattern useful to ensure that just a single instance of a class was created

# Singleton Patterns for ASP.NET « Coffee => Coder => Code said on 01 June, 2011 07:35 AM

Pingback from  Singleton Patterns for ASP.NET « Coffee => Coder => Code

# Singleton Patterns for ASP.NET | CMS News Today said on 02 June, 2011 06:40 AM

Pingback from  Singleton Patterns for ASP.NET | CMS News Today

# ASP.Net & MVC | Pearltrees said on 29 August, 2012 02:11 AM

Pingback from  ASP.Net & MVC | Pearltrees

# ASP.Net & MVC | Pearltrees said on 29 August, 2012 02:12 AM

Pingback from  ASP.Net & MVC | Pearltrees

# The ASP.NET Singleton-per-Request pattern | Things worth sharing said on 18 December, 2012 05:26 PM

Pingback from  The ASP.NET Singleton-per-Request pattern | Things worth sharing

This site

Search

Go

This Blog

News

Syndication

Sponsors

  • MaximumASP