Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Better way of doing strongly-typed ASP.NET MVC sessions

Tags:

I am developing an ASP.NET MVC project and want to use strongly-typed session objects. I have implemented the following Controller-derived class to expose this object:

public class StrongController<_T> : Controller
    where _T : new()
{
    public _T SessionObject
    {
        get
        {
            if (Session[typeof(_T).FullName] == null)
            {
                _T newsession = new _T();
                Session[typeof(_T).FullName] = newsession;
                return newsession;
            }
            else
                return (_T)Session[typeof(_T).FullName];
        }
    }

}

This allows me to define a session object for each controller, which is in line with the concept of controller isolation. Is there a better/more "correct" way, perhaps something that is officially supported by Microsoft?

like image 332
David Pfeffer Avatar asked Nov 10 '09 20:11

David Pfeffer


People also ask

Which is better TempData or session in MVC?

TempData is ideal for short-lived things like displaying validation errors or other messages that we don't need to persist for longer than a single request. Session is ideal choice when we need to persist data for extended periods of time i.e. it is used to store data which is required throughout user session.

Is it good to use session in MVC?

It is perfectly OK to use sessions in ASP.NET MVC, especially in the shopping cart scenario of yours.


2 Answers

This way other objects won't have access to this object (e.g. ActionFilter). I do it like this:

public interface IUserDataStorage<T>
{
   T Access { get; set; }
}

public class HttpUserDataStorage<T>: IUserDataStorage<T>
  where T : class
{
  public T Access
  {
     get { return HttpContext.Current.Session[typeof(T).FullName] as T; }
     set { HttpContext.Current.Session[typeof(T).FullName] = value; }
  }
}

Then, I can either inject IUserDataStorage into controller's constructor, or use ServiceLocator.Current.GetInstance(typeof(IUserDataStorage<T>)) inside ActionFilter.

public class MyController: Controller
{
   // automatically passed by IoC container
   public MyController(IUserDataStorage<MyObject> objectData)
   {
   }
}

Of course for cases when all controllers need this (e.g. ICurrentUser) you may want to use property injection instead.

like image 171
queen3 Avatar answered Sep 17 '22 19:09

queen3


This might be better for what you want. I would just create an extension method that can access your session. The added benefit to the extension method is that you no longer have to inherit from a controller, or have to inject a dependency that really isn't necessary to begin with.

public static class SessionExtensions {
  public static T Get<T>(this HttpSessionBase session, string key)  {
     var result;
     if (session.TryGetValue(key, out result))
     {
        return (T)result;
     }
     // or throw an exception, whatever you want.
     return default(T);
   }
 }


public class HomeController : Controller {
    public ActionResult Index() {
       //....

       var candy = Session.Get<Candy>("chocolate");

       return View(); 
    }

}
like image 34
Khalid Abuhakmeh Avatar answered Sep 21 '22 19:09

Khalid Abuhakmeh