Сеанс нульовий у конструкторах контролерів ASP.Net MVC


88

Чому Session є нульовим у конструкторах контролерів? Доступ до нього можна отримати за допомогою методів Action. Імовірно, оскільки рамка маршрутизації MVC відповідає за створення контролера, він просто не (повторно) створив сесію на той момент.

Хтось знає, чи це за задумом, і якщо так, то чому?

[Мені вдалося обійти проблему, використовуючи шаблон лінивого завантаження.]

Відповіді:


79

Андрій має рацію - це нуль, тому що під час роботи в рамках ASP.NET MVC HttpContext (і, отже, HttpContext.Session) не встановлюється, коли клас контролера створюється, як ви могли б очікувати, але він встановлюється ("вводиться") пізніше класом ControllerBuilder. Якщо ви хочете краще зрозуміти життєвий цикл, ви можете або витягнути платформу ASP.NET MVC (джерело доступне), або звернутися до: цієї сторінки

Якщо вам потрібен доступ до сеансу, то одним із способів буде перевизначення методу "OnActionExecuting" і доступ до нього там, оскільки він буде доступний до того часу.

Однак, як припускає Андрій, якщо ваш код залежить від сеансу, тоді потенційно може бути важко написати модульні тести, тому, можливо, ви можете розглянути можливість обгортання сеансу в допоміжний клас, який потім можна замінити на інший, не- веб-версія, коли вона працює під модульними тестами, тому від'єднайте ваш контролер від Інтернету.


3
Я не впевнений, що це правильне твердження про HttpContext. Він фактично побудований на початку всього потоку. Ви можете прочитати трохи про докладному потоці тут beletsky.net/2011/06/inside-aspnet-mvc-route-to-mvchanlder.html або ви можете використовувати відбивач і знайти себе , коли HttpContext був екземпляр - його навколо лінії 1556 в httpruntime .cs.
Олексій Щербак

@AlexeyShcherbak Це може бути вже побудовано - OP стосується того, чи встановлений він у властивості Session контролера MVC. тобто публічна сесія HttpSessionStateBase {get; } на System.Web.Mvc.Controller Це різні речі.
MemeDeveloper

61

На додаток до інших відповідей тут, хоча Controller.Sessionце не заповнено в конструкторі, ви все одно можете отримати доступ до сеансу через:

System.Web.HttpContext.Current.Session

зі стандартним застереженням, що це потенційно знижує перевірку вашого контролера.


3
Тип кожного з цих двох властивостей сеансу різний, що може мати значення, якщо ви збираєтеся зберегти посилання на сам стан сеансу.
BrianCooksey 11.03.13

@BrianCooksey що ​​відрізняється?
MichaelMao

1
Controller.Session має тип System.Web.HttpSessionStateBase (див. Msdn.microsoft.com/en-us/library/… ), але System.Web.HttpContext.Current.Session має тип System.Web.SessionState.HttpSessionState (див. Msdn .microsoft.com / en-us / library /… )
BrianCooksey

Стара відповідь, але я хотів сказати, що System.Web.HttpContext.Current.Sessionце також nullу програмі інсталяції MVC VS2019.
jp2code

11

Сесія вводиться пізніше протягом життєвого циклу. Навіщо взагалі потрібен сеанс у конструкторі? Якщо він вам потрібен для TDD, вам слід обернути сеанс у об'єкт, який можна висміювати.


1
Для того, щоб додати до Андрія Rinea, це конкретний приклад методики , згаданої їм: iridescence.no/post / ...
murki

4
Я хочу отримати доступ до сеансу під час моїх конструкторів, щоб мати доступ до раніше збереженої інформації про сеанс. Так, я міг би замінити метод OnActionExecuting, але це, безумовно, не елегантне рішення.
Кріс Арнольд

8

Ви можете замінити метод Initialize, щоб встановити сеанс.

protected override void Initialize(RequestContext requestContext)

2

Якщо ви використовуєте контейнер IoC, спробуйте ввести і використовувати HttpSessionStateBaseзамість Sessionоб’єкта:

private static Container defaultContainer()
{
    return new Container(ioc =>
    {
        // session manager setup
        ioc.For<HttpSessionStateBase>()
           .Use(ctx => new HttpSessionStateWrapper(HttpContext.Current.Session)); 
    });
}

2

Ця відповідь може бути корисною для деяких людей

Якщо ми замінюємо метод Initialize, то нам потрібно ініціалізувати базовий клас контекстом запиту: base.Initialize (requestContext);

protected override void Initialize(RequestContext requestContext)
        {
            base.Initialize(requestContext);
           

        }

Корисно. Зверніть увагу, що підпис методу protected override void Initialize(System.Web.Routing.RequestContext requestContext).
Martin_W
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.