Asp.net-Mvc

我應該在哪裡附加 ASP.NET MVC3 中的自定義使用者上下文會話包裝器?

  • July 14, 2011

我已經閱讀了許多關於 MVC 中 Session-scoped data 的文章,但我仍然不清楚在解決方案中包含自定義 Session 包裝器的正確位置。

我想從 IPrincipal 獲取目前使用者的使用者名,載入有關該使用者的附加資訊並將其儲存在 Session 中。然後我想從Controller 和 View訪問該使用者數據。

以下方法似乎都不適合我想做的事情。

選項 1:直接訪問 Session 集合

每個人似乎都同意這是一個壞主意,但老實說,這似乎是最簡單的方法。但是,它不會使使用者對視圖可用。

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;
     }
  }
}

選項 2:將 Session 注入到類建構子 論壇文章中

這個選項看起來不錯,但我仍然不確定如何將它附加到控制器和視圖。我可以在控制器中新建它,但它不應該作為依賴注入嗎?

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
     }
  }
}

選項 3:使用 Brad Wilson 的 StatefulStorage 類

Brad Wilson在他的演講中介紹了他的 StatefulStorage 類。它是一組聰明而有用的類,包括介面並使用建構子注入。但是,它似乎使我走上了與選項 2 相同的道路。它使用介面,但我不能使用 Container 來注入它,因為它依賴於靜態工廠。即使我可以注入它,它是如何傳遞給 View 的。每個 ViewModel 都必須有一個帶有可設置 User 屬性的基類嗎?

選項 4:使用類似於 Hanselman IPrincipal ModelBinder的東西

我可以將 User 作為參數添加到 Action 方法中,並使用 ModelBinder 從 Session 中對其進行水合。在需要的地方添加它似乎有很多成本。另外,我仍然必須將其添加到 ViewModel 以使其對 View 可用。

public ActionResult Edit(int id, 
  [ModelBinder(typeof(IPrincipalModelBinder))] IPrincipal user)
{ ... }

我覺得我想多了,但似乎也應該有一個明顯的地方來做這種事情。我錯過了什麼?

我的會話方法:

帶介面的覆蓋會話:

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

使用 HttpContext.Current.Session 實現介面:

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); }
   }
}

注入控制器:

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

   public BaseController(ISessionWrapper sessionWrapper)
   {
       SessionWrapper = sessionWrapper;
   }
}

Ninject 依賴:

Bind<ISessionWrapper>().To<HttpContextSessionWrapper>()

ViewData當您想在母版頁中使用它並在特定視圖中使用視圖模型時,您可以傳遞一些常用資訊。

引用自:https://stackoverflow.com/questions/5060804