views:

152

answers:

1

Obviously, the typical WebForms approach won't work. How does one track a user in an MVC world?

+9  A: 

Session works exactly the same way it worked in Webforms. If you want to store simple information, use forms authentication cookie. If you want to store a content of shopping cart, Session is the place to go. I wrote a blog entry about using Session with ASP.NET:

Lets say that we want to store an integer variable in Session.We will create wrapper around of Session variable that makes it look nicer:

First we define interface:

public interface ISessionWrapper
{
    int SomeInteger { get; set; }
}

Then we make HttpContext implementation:

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 int SomeInteger
    {
        get { return GetFromSession<int>("SomeInteger"); }
        set { SetInSession("SomeInteger", value); }
    }
}

GetFromSession and SetInSession are helper method that make taking and setting data in Session easier. SomeInteger property uses these methods.

Then we define our base controller (applicable to ASP.NET MVC):

public class BaseController : Controller
{
    public ISessionWrapper SessionWrapper { get; set; }

    public BaseController()
    {
        SessionWrapper = new HttpContextSessionWrapper();
    }
}

If you want to use Session outside controller, you just create or inject new HttpContextSessionWrapper().

You can replace SessionWrapper with ISessionWrapper mock in Controller tests, so it is not dependent on HttpContext anymore. Session is also more easy to use, because instead of calling (int)Session["SomeInteger"], you call SessionWrapper.SomeInteger. It looks nicer, isn't it?

You may be tempted by idea of creating static class that covers Session object and doesn't require to define any interfaces or initialization in BaseController, but it loses some of advantages, specially when it comes to testing and replacing with other implementation.

LukLed
Why would you write an interface and a wrapper class when the framework already provides you `HttpContext.Current.Session[key]`?
çağdaş
Because: 1. var cart = (List<CartItems>)HttpContext.Current.Session[key] looks hideous and SessionWrapper.CartItems looks nice. 2. It is easier to write test for ISessionWrapper. ISessionWrapper can be easily mockable and replaced with content for various test scenarios. 3. It looses dependency. If I wanted to use another storage instead of Session, I just create other ISessionWrapper implementation. You have to replace code in every controller that uses Session.
LukLed
@LukLed, good points. Though I can't take the downvote back unless you edited the post.
çağdaş