Куда мне прикрепить настраиваемую оболочку сеанса пользовательского контекста в ASP.NET MVC3?

Я прочитал много сообщений о данных с привязкой к сеансу в MVC, но мне все еще неясно, где лучше всего включить пользовательскую оболочку сеанса в решение.

Я хочу получить имя пользователя текущего пользователя из IPrincipal, загрузить дополнительную информацию об этом пользователе и сохранить ее в сеансе. Затем я хочу получить доступ к этим данным пользователя из Контроллера и Представления .

Ни один из следующих подходов не подходит для того, что я хочу сделать.

Вариант 1: Доступ к коллекции сеансов напрямую

Кажется, все согласны , что это плохая идея , но, честно говоря, это самая простая вещь, которая работает. Однако он не делает пользователя доступным для представления.

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: Внедрение сеанса в конструктор класса сообщение на форуме

Этот вариант кажется довольно хорошим, но я все еще не уверен, как прикрепить это к контроллеру и представлению. Я мог бы добавить что-то новое в Контроллер, но разве не следует вводить его как зависимость?

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: Используйте класс StatefulStorage Брэда Уилсона

В его презентации Брэд Уилсон описывает свое StatefulStorage учебный класс. Это умный и полезный набор классов, которые включают интерфейсы и используют внедрение конструктора. Однако, похоже, он ведет меня по тому же пути, что и вариант 2. Он использует интерфейсы, но я не мог ' t использовать Контейнер для его внедрения, потому что он полагается на статическую фабрику. Даже если бы я мог ввести его, как он передается в представление. Должна ли каждая ViewModel иметь базовый класс с настраиваемым свойством User?

Вариант 4: Используйте что-то похожее на Hanselman IPrincipal ModelBinder

Я мог бы добавить пользователя в качестве параметра к методу Action и использовать ModelBinder, чтобы увлажнить его из сеанса. Похоже, что добавлять его везде, где это необходимо, слишком дорого. Кроме того, мне все равно придется добавить его в ViewModel, чтобы сделать его доступным для View.

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

Я чувствую, что слишком много думаю об этом, но также кажется, что должно быть очевидное место для таких вещей. Что мне не хватает?

16
задан Community 23 May 2017 в 12:08
поделиться