title: Where should I attach a custom user-context Session wrapper in ASP.NET MVC3?
body: <p>I have read many posts on Session-scoped data in MVC, but I am still unclear where is the right place to include a custom Session wrapper into the solution.  </p>
  
  <p>I want to get the Username of the current user from the IPrincipal, load additional information about that User and store it in the Session.  Then I want to access that User data from <strong><em>the Controller and the View</em></strong>.</p>
  
  <p>None of the following approaches seem to fit what I want to do.</p>
  
  <p><strong>Option 1 : Access the Session collection directly</strong></p>
  
  <p>Everyone seems to agree <a href="https://stackoverflow.com/questions/560084/session-variables-in-asp-net-mvc">this is a bad idea</a>, but honestly it seems like the simplest thing that works.  However, it doesn't make the User available to the view.</p>
  
  <pre><code>public class ControllerBase : Controller {
     public ControllerBase() : this(new UserRepository()) {}
     public ControllerBase(IUserRepository userRepository) {
        _userRepository = userRepository;
     }
     protected IUserRepository _userRepository = null;
     protected const string _userSessionKey = "ControllerBase_UserSessionKey";
     protected User {
        get { 
           var user = HttpContext.Current.Session[_userSessionKey] as User;
           if (user == null) {
              var principal = this.HttpContext.User;
              if (principal != null) {
                 user = _userRepository.LoadByName(principal.Identity.Name);
                 HttpContext.Current.Session[_userSessionKey] = user;
              }
           }
           return user;
        }
     }
  }
  </code></pre>
  
  <p><strong>Option 2: Injecting the Session into the class constructor</strong> <a href="http://forums.asp.net/t/1590118.aspx/1?Injecting+the+session+into+a+wrapper+class" rel="nofollow noreferrer">forum post</a></p>
  
  <p>This option seems pretty good, but I am still not sure how to attach it to the Controller and the View.  I could new-it-up in the Controller, but shouldn't it be injected as a dependency?</p>
  
  <pre><code>public class UserContext {
     public UserContext() 
         : this(new HttpSessionStateWrapper(HttpContext.Current.Session), 
                new UserRepository()) { } 
  
     public UserContext(HttpSessionStateBase sessionWrapper, IUserRepository userRepository) { 
        Session = sessionWrapper;
        UserRepository = userRepository; 
     } 
  
     private HttpSessionStateBase Session { get; set; }
     private IUserRepository UserRepository{ get; set; }
  
     public User Current { 
        get {
           //see same code as option one
        }
     }
  }
  </code></pre>
  
  <p><strong>Option 3 : Use Brad Wilson's StatefulStorage class</strong></p>
  
  <p>In his <a href="http://bradwilson.typepad.com/blog/2011/02/advanced-aspnet-mvc-3-presentation.html" rel="nofollow noreferrer">presentation</a> Brad Wilson features his StatefulStorage class. It is a clever and useful set of classes which include interfaces and uses constructor injection.  However, it seems to lead me down the same path as Option 2.  It uses interfaces, but I couldn't use the Container to inject it because it relies on a static factory. Even if I could inject it, how does it get passed to the View.  Does every ViewModel have to have a base class with a setable User property?</p>
  
  <p><strong>Option 4 : Use something similar to the Hanselman <a href="http://www.hanselman.com/blog/IPrincipalUserModelBinderInASPNETMVCForEasierTesting.aspx" rel="nofollow noreferrer">IPrincipal ModelBinder</a></strong></p>
  
  <p>I could add the User as a parameter to the Action method and use a ModelBinder to hydrate it from the Session. This seems like a lot of overhead to add it everywhere it is needed.  Plus I would still have to add it to the ViewModel to make it available to the View.</p>
  
  <pre><code>public ActionResult Edit(int id, 
     [ModelBinder(typeof(IPrincipalModelBinder))] IPrincipal user)
  { ... }
  </code></pre>
  
  <p>I feel like I am overthinking this, but it also seems like there should be an obvious place to do this sort of thing. What am I missing?</p>