web-dev-qa-db-ja.com

ASP.Net MVC Controllerコンストラクターのセッションnull

コントローラーのコンストラクターでセッションがnullになるのはなぜですか?アクションメソッドからアクセスできます。おそらく、MVCルーティングフレームワークはコントローラーの更新を担当しているため、その時点でセッションを(再)インスタンス化していないだけです。

これが仕様によるものであるかどうか、誰が知っていますか?

[Lazy Loading Patternを使用することで問題を回避できました。]

83
Chris Arnold

Andreiは正しいです-ASP.NET MVCフレームワークの下で実行する場合、コントローラークラスが予想どおりに構築されたときにHttpContext(したがってHttpContext.Session)が設定されていないが、後で設定(「注入」)されるため、nullですControllerBuilderクラスによって。ライフサイクルをよりよく理解したい場合は、ASP.NET MVCフレームワークをプルダウンするか(ソースが利用可能)、または このページ を参照してください。

Sessionにアクセスする必要がある場合、1つの方法は、「OnActionExecuting」メソッドをオーバーライドしてそこにアクセスすることです。

ただし、Andreiが示唆しているように、コードがSessionに依存している場合、ユニットテストを書くのが難しい可能性があるため、ヘルパークラスでSessionをラップすることを検討できます。ユニットテストで実行する場合はWebバージョン。したがって、コントローラーをWebから切り離します。

73
Andrew W

ここでの他の回答に加えて、Controller.Sessionはコンストラクタに設定されていませんが、次の方法でセッションにアクセスできます。

System.Web.HttpContext.Current.Session

これにより、コントローラーのテスト容易性が低下する可能性があるという標準的な注意事項があります。

57

セッションはライフサイクルの後半で注入されます。とにかくコンストラクターでセッションが必要なのはなぜですか? TDDに必要な場合は、セッションをモック可能なオブジェクトにラップする必要があります。

10
Andrei Rînea

Initializeメソッドをオーバーライドして、セッションを設定できます。

protected override void Initialize(RequestContext requestContext)
8
Funlover

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
VahidN

この答えは、一部の人々にとって役立つかもしれません

Initializeメソッドをオーバーライドする場合、リクエストコンテキストでベースクラスを初期化する必要があります:base.Initialize(requestContext);

protected override void Initialize(RequestContext requestContext)
        {
            base.Initialize(requestContext);
            if (web == null && Session != null && Session["APPLIANCE_URL"] != null)
            {
                web = new WebServices((String)Session["APPLIANCE_URL"]);
            }

        }