Сессия null в конструкторах диспетчера ASP.NET MVC

Почему Session null в конструкторах контроллеров? Доступ к нему возможен из методов Action. Предположительно, поскольку структура MVC Routing отвечает за создание контроллера контроллера, он просто не выполнил (повторно) создание сеанса в этой точке.

Кто-нибудь знает, если это по дизайну, и если да, то почему?

[Мне удалось обойти проблему, используя шаблон Lazy Loading.]

Ответ 1

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

Если вам нужно получить доступ к сеансу, одним из способов было бы переопределить метод "OnActionExecuting" и получить к нему доступ, так как он будет доступен к этому времени.

Однако, как указывает Андрей, если ваш код зависит от сеанса, тогда потенциально может быть трудно написать модульные тесты, поэтому, возможно, вы можете рассмотреть возможность переноса сеанса в вспомогательный класс, который затем может быть заменен на другой, не веб-версию при работе в модульных тестах, поэтому удаление вашего контроллера из Интернета.

Ответ 2

В дополнение к другим ответам здесь, в то время как Controller.Session не заполняется в конструкторе, вы можете получить доступ к сеансу через:

System.Web.HttpContext.Current.Session

со стандартным предупреждением о том, что это потенциально снижает вашу тестируемость контроллера.

Ответ 3

Сессия вводится позже в жизненном цикле. Зачем вам нужен сеанс в конструкторе? Если вам это нужно для TDD, вы должны перенести сеанс в макетируемый объект.

Ответ 4

Вы можете переопределить метод Initialize, чтобы установить сеанс.

protected override void Initialize(RequestContext requestContext)

Ответ 5

Если вы используете контейнер IoC, попробуйте ввести и использовать HttpSessionStateBase вместо объекта Session:

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