Каков принятый шаблон для реализации Session на сайтах ASP.NET MVC? - PullRequest
5 голосов
/ 06 марта 2010

Очевидно, что типичный подход WebForms не будет работать. Как отследить пользователя в мире MVC?

Ответы [ 2 ]

24 голосов
/ 06 марта 2010

Сессия работает точно так же, как и в Webforms. Если вы хотите хранить простую информацию, используйте cookie для проверки подлинности форм. Если вы хотите сохранить содержимое корзины покупок, Session - это то, что вам нужно. Я написал в блоге запись о , используя Session with ASP.NET :

Допустим, мы хотим сохранить целочисленную переменную в Session. Мы создадим обертку вокруг переменной Session, которая будет выглядеть лучше:

Сначала мы определим интерфейс:

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

Затем мы делаем реализацию HttpContext:

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

GetFromSession и SetInSession - вспомогательный метод, упрощающий получение и настройку данных в Session. Свойство SomeInteger использует эти методы.

Затем мы определяем наш базовый контроллер (применимый к ASP.NET MVC):

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

    public BaseController()
    {
        SessionWrapper = new HttpContextSessionWrapper();
    }
}

Если вы хотите использовать Session вне контроллера, вы просто создаете или внедряете новый HttpContextSessionWrapper ().

Вы можете заменить SessionWrapper на макет ISessionWrapper в тестах контроллера, чтобы он больше не зависел от HttpContext. Session также более прост в использовании, потому что вместо вызова (int) Session ["SomeInteger"], вы вызываете SessionWrapper.SomeInteger. Это выглядит лучше, не так ли?

Вас может соблазнить идея создания статического класса, который охватывает объект Session и не требует определения каких-либо интерфейсов или инициализации в BaseController, но он теряет некоторые преимущества, особенно когда речь идет о тестировании и замене на другую реализацию.

2 голосов
/ 16 июля 2011

Вот код, который я использую, только немного «улучшенная» версия вышеуказанной версии:

private T GetFromSessionStruct<T>(string key, T defaultValue = default(T)) where T : struct 
{
    object obj = HttpContext.Current.Session[key];
    if (obj == null)
    {
        return defaultValue;
    }
    return (T)obj;
}

private T GetFromSession<T>(string key) where T : class
{
    object obj = HttpContext.Current.Session[key];
    return (T)obj;
}

private T GetFromSessionOrDefault<T>(string key, T defaultValue = null) where T : class
{
    object obj = HttpContext.Current.Session[key];
    if (obj == null)
    {
        return defaultValue ?? default(T);
    }
    return (T)obj;
}

private void SetInSession<T>(string key, T value)
{
    if (value == null)
    {
        HttpContext.Current.Session.Remove(key);
    }
    else
    {
        HttpContext.Current.Session[key] = value;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...