我應該在哪裡附加 ASP.NET MVC3 中的自定義使用者上下文會話包裝器?
我已經閱讀了許多關於 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當您想在母版頁中使用它並在特定視圖中使用視圖模型時,您可以傳遞一些常用資訊。