Я прочитал много постов о данных в формате Session в MVC, но мне все еще неясно, где находится правильное место для включения пользовательской оболочки Session в решение.
Я хочу получить имя пользователя текущего пользователя из 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. Он использует интерфейсы, но я не смог использовать контейнер для его внедрения, потому что он опирается на статическую фабрику.Даже если бы я мог внедрить это, как это передано Представлению.Должен ли каждый ViewModel иметь базовый класс с настраиваемым свойством User?
Вариант 4: использовать что-то похожее на Hanselman IPrincipal ModelBinder
Я мог бы добавить пользователя в качестве параметра к методу Action и использовать ModelBinder для его гидратации из сеанса.Кажется, что это требует много времени, чтобы добавить его везде, где это необходимо.Кроме того, мне все равно пришлось бы добавить его в ViewModel, чтобы сделать его доступным для View.
public ActionResult Edit(int id,
[ModelBinder(typeof(IPrincipalModelBinder))] IPrincipal user)
{ ... }
Мне кажется, что я обдумываю это, но, похоже, для этого должно быть очевидное место.Такие вещи.Чего мне не хватает?