Geeks With Blogs
Mike Nichols - SonOfNun Technology If I were the captain on a big steamboat...

In a previous post, I asked if anyone had a good pattern for accessing Session data from a lower layer (ie, Service Layer) in a multi-layered ASP.NET app WITHOUT reference System.Web. This would be handy to manage all session data from a lower level. Greg Young kindly replied and pointed me in a great direction that led to a pattern I am happy with now.

The first task is to implement an interface that we'll use to abstract away the Session implementation:

public interface ISessionDataProvider

{

object this[string name] { get;set;}

object this[int indexer] { get;set;}

}

Since we are working in an ASP.NET app, let's wrapp the HttpContextSession in an object that implements this new interface:

/// <summary>

/// Wraps HttpContext Current Session for injection into facade layer. Pages/presenters

/// should use this object for storing session data.

/// </summary>

public class WebSessionDataProvider : ISessionDataProvider, IDictionary

{

public object this[string name]

{

get

{

return HttpContext.Current.Session[name];

}

set

{

HttpContext.Current.Session[name] = value;

}

}

public object this[int index]

{

get

{

return HttpContext.Current.Session[index];

}

set

{

HttpContext.Current.Session[index] = value;

}

}

… implement remainder of Idictionary members

}

We'll be applying the Model-View-Presenter pattern, so we'll inject the implemented ISessionDataProvider above into the base Presenter class:

public abstract class <TView,TService> where TView: IView where TService:IService

{

private readonly TView _view;

protected TView View

{

get

{

return _view;

}

}

private readonly TService _service;

protected TService Service

{

get

{

return _service;

}

}

protected ISessionDataProvider Session

{

get

{

return SessionManager.Instance.GetCurrentSession();

}

}

 

public PresenterBase(TView view, TService service, ISessionDataProvider session)

{

_view = view;

_service = service;

SessionManager.Instance.SetCurrentSession(session);

}

}

 

 

Now we just need to wire up our presenter in the Page_Load event, passing the implementation of the ISessionDataProvider into the Presenter:

protected void Page_Load(object sender, EventArgs e)

{

WebSessionDataProvider session = new WebSessionDataProvider();

AccountCategoryPresenter presenter =

new AccountCategoryPresenter(AccountCategory1, AccountingFacade.Instance,session);

AccountCategory1.AttachPresenter(presenter);

presenter.Initialize();

}

 

 

The class that manages the Session in the Service Layer (or beneath) will be implemented as a Singleton here and provides methods for fetching/setting the ISessionDataProvider using IoC (again). The comments should explain what happens:

/// <summary>

/// Singleton IoC container for managing sessions that might come from a variety of UI

/// environments. Inspired (stolen) from an email exchange with Greg Young at

/// http://codebetter.com/blogs/gregyoung/. This container accepts any provider that implements

/// the <see cref="ISessionDataProvider"/> interface.

/// </summary>

/// <remarks>

/// For cross-threading ops, consider the following remark from Greg:

/// "The reason I ask if if you have cross thread behaviors it that this will obviously not work very

/// well if you are switching threads (but keeping the same context) if you want to do this the best way

/// of doing it is to move your context to the new thread, this would require a context map as well

/// (where the manager pointed to the map) .. you could then use the map item

/// (once brokerred to the other thread to reset your current scope for that thread from within the facade

/// layer itself but this can be a much more tricky scenario ... )".

/// </remarks>

public class SessionManager

{

 

#region Singleton Instantiation

SessionManager() { }

public static SessionManager Instance

{

get{ return Singleton.instance; }

}

class Singleton

{

static Singleton() { }

internal static readonly SessionManager instance =

new SessionManager();

}

#endregion

 

private Hashtable _hash = new Hashtable();

 

/// <summary>

/// Provider must implement the <see cref="ISessionDataProvider"/> interface.

/// </summary>

/// <param name="scope"></param>

public void SetCurrentSession(ISessionDataProvider scope)

{

lock (_hash)

{

_hash[Thread.CurrentThread.GetHashCode()] = scope;

}

}

/// <summary>

/// Cross-threaded operations will not be supported here yet (if keeping the same context).

/// See remarks above if implementing cross-threading, uni-contextual processes.

/// </summary>

/// <returns></returns>

public ISessionDataProvider GetCurrentSession()

{

return _hash[Thread.CurrentThread.GetHashCode()] as ISessionDataProvider;

}

Now, I just need to consume my abstracted Session in the Facade (Service) layer:

/// <summary>

/// Session data provider for the current thread...only applies to

/// use cases where multi-threading is not required (typical)

/// </summary>

public SessionManager Session

{

get

{

return SessionManager.Instance.GetCurrentSession();

}

}

 

public void DoMethod()

{

object obj = Session[“key”] ;

}

This should help me for testing any kind of mock session data. Posted on Friday, June 30, 2006 2:57 PM OOP, Patterns, Architecture | Back to top


Comments on this post: Session data pattern for multi-layered apps and Model-View-Presenter ASP.NET strategies

# re: Session data pattern for multi-layered apps and Model-View-Presenter ASP.NET strategies
Requesting Gravatar...
Mike,
I stumbled upon your blog today and read through your last 15 or so posts. I too am always on the quest for the perfect architecture :) I've learned a lot of things from reading various blogs over the past year and have latched on to various tools like OR/M, test automation, dependency injection, etc.

I see from a lot of your code samples that you heavily use the Singelton pattern for your Service layer. I wanted to see if you have ever checked out Castle Windsor? It is a microkernel/dependency injection framework that takes the place of the Singleton pattern. It took me several weeks to learn about it and work through various articles and tutorials, but finally the lighted kicked on and I had one of those 'Whoa' moments. It makes testing and configuration much easier and fits well with other tools.

Anyways, your're on my blog roll now and I look forward to reading about your continued adventures in coding.

-Bill
Left by Bill Pierce on Jul 12, 2006 8:43 AM

# re: Session data pattern for multi-layered apps and Model-View-Presenter ASP.NET strategies
Requesting Gravatar...
Truthfully about a year ago I was a hard-core fan of CSLA, knew what unit tests were but really didn't understand them, and thought interfaces were a waste of time! My projects worked, met the requirements and customer's even liked them. But it was difficult to add features, make customizations, track down bugs, etc.

All the hype surrounding Ruby on Rails got me interested but I wasn't going to tackle a new language. So I found MonoRail from Castle. I spent a few weeks looking at it when I had time and it felt very backwards. I finally tried a little test project and suddenly things clicked and I was very impressed. MonoRail led me to ActiveRecord and nHibernate and eventually Windsor.

Long story short, I don't think I can speak intelligently about why Windsor is better/worse than another DI framework (except maybe CAB from M$, tried that and it seemed needlessly complicated). I doubt I'm using it to its full potential but that's why I love development, always room for improvement.

-Bill
Left by Bill Pierce on Jul 14, 2006 4:51 AM

# re: Session data pattern for multi-layered apps and Model-View-Presenter ASP.NET strategies
Requesting Gravatar...
is it possible to download your source somewhere?
many thnx
tammy
Left by tammy on Mar 03, 2009 10:05 AM

Your comment:
 (will show your gravatar)


Copyright © Mike Nichols | Powered by: GeeksWithBlogs.net