ASP .Net MVC 3 HTTPContext Wrapper

2020-07-20 07:44发布

问题:

In an effort to move to TDD and unit testable code I have read that I should be using an HttpContext wrapper. In my service layer as well as in my controllers I have to access the HttpContext Session for some data I have stored there.

Can someone provide an example of an HttpContext Wrapper implementation for MVC 3

回答1:

The MVC Runtime already provides a HttpContextWrapper. What you need to implement is a wrapper around Session state, and encapsulate the fact that state is being accessed through HttpContext so that you can use DI or a Mocking framework to create a non-HttpContext backed SessionWrapper for your tests. Brad Wilson provides some good information on how to do this. However, if you don't want to wade through the video (which contains advanced topics) here is the gist for wrapping Session:

Create an interface representing strongly typed object you could typically access through Session:

public interface ISessionWrapper
{
    public UserPreferences CurrentUserPreferences{get;set;}
    ...
}

Create an implementation of the interface that uses Session as a backing store:

public class HttpContextSessionWrapper : ISessionWrapper
{
    private T GetFromSession<T>(string key)
    {
        return (T) HttpContext.Current.Session[key];
    }

    private void SetInSession(string key, object value)
    {
        HttpContext.Current.Session[key] = value;
    }

    public UserPreferences CurrentUserPreferences
    {
        get { return GetFromSession<UserPreferences>("CurrentUserPreferences"); }
        set { SetInSession("CurrentUserPreferences", value); }
    }

    ...
}

Resolve the instance in your Controller using DependencyResolver (or preferably this is done through you DI framework of choice). Assuming you are using the SessionWrapper in a majority of Controllers, this could be done in a common BaseController:

var SessionWrapper = DependencyResolver.Current.GetService<ISessionWrapper>();