Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

(ASP.NET) Accessing HttpContext.Current and Other System.Web Components from Low Level Tiers

0.00/5 (No votes)
15 Jan 2012CPOL3 min read 24.2K  
Generally when you divide up your tiers, your lower level tiers lose access to HttpContext.Current and other important presentation components. This pattern works easily around that issue.
Once you split your application into multiple tiers, you quickly find that the business and data tiers don't (well shouldn't) have direct access to the HttpContext.Current object and the .Application, .Request, .Items, and .Session collections.

The separation allows you to switch UIs or UI libraries without having to overhaul the engine of the application, and is good for organisation, so it's good practice, but has its hassles.

How do you store ASP.NET application state, such as certain database connection parameters, or a database connection object, if you don't have application to HttpContext.Current.Application?

One way is to use the provider pattern and abstract the state management behind a simple state framework that has two parts.

The first part is a library with a base class and a static property to hold a derived instance of it.

Here's an example of the base state component:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.State/BaseStateProvider.cs

Here's an example of the static property which holds a copy of the state component:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.State/StateAccess.cs

These are in a library which has no reference to System.Web and therefore no way to access HttpContext.Current. This state library is at the core of the application and all projects requiring state access should reference it.

Now to actually provide all of those low level components access to the state collections offered by HttpContext.Current, we introduce the web specific state component.

The web specific state component inherits BaseStateProvider and overrides all of the functions. The web specific state component is defined in the presentation library and passed down to the lower levels to use. This allows them to interact with the System.Web components indirectly by overriding the functions.

Here's an example of the web specific state provider:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Web/State/WebStateProvider.cs

Each set of functions corresponds to a specific scope and a different state collection.

During Application_Start, Session_Start, and Application_BeginRequest, the web state provider component is initialized and assigned to StateAccess.State (if not already initialized).

Here's an example of the initialization call in ApplicationContext, which inherits HttpApplication and is the code behind for the Global.asax file:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Web/ApplicationContext.cs#180

Here's an example of the initializer:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Web/State/StateProviderInitializer.cs#41

The initializer above uses modified provider pattern code taken from the MSDN reference and could easily be simplified to just:

C#
StateAccess.State = new WebStateProvider();


So as a result, the library structure is:

Web

Business

Data

Entities

Configuration

Diagnostics

State

The State library is at the center/base. Pretty much every other library will reference the core State library, which contains the base class and static property to hold it.

The web specific state components are in another library in the web tier either in their own library or within a general web assembly.

Now because of this setup, I can create a db4o IObjectServer in the data tier and store it using:
C#
StateAccess.State.SetApplication(serverKey, objectServer);

Such as:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Data.Db4o/Db4oDataStore.cs#75

Then retrieve it again using:
C#
IObjectServer objectServer = (IObjectServer)StateAccess.State.GetApplication(serverKey);

Such as:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Data.Db4o/Db4oDataStore.cs#72

This is despite the data assemblies having no direct reference to the System.Web library it's being stored in HttpContext.Current.Application. This is a good place to store something if you only want a single instance of it for the life of your application.

So the entire project can be switched to a desktop GUI or another UI just by providing a state component for that.
The general StateProvider would likely be sufficient for most cases, but a custom one can be provided if needed:
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.State/StateProvider.cs
It gets used during testing to remove any dependencies on the System.Web library and HttpContext.Current.

This pattern can be reused for a multitude of situations, with a little imagination. You'll likely need to create code specific to that solution.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)