web-dev-qa-db-ja.com

コントローラーのインスタンスのHttpContextがASP.netMVCでnull

これはコントローラーを使用する正しい方法ではないかもしれませんが、私はこの問題に気づき、それを修正する方法を見つけていませんでした。

public JsonResult SomeControllerAction() {

    //The current method has the HttpContext just fine
    bool currentIsNotNull = (this.HttpContext == null); //which is false    

    //creating a new instance of another controller
    SomeOtherController controller = new SomeOtherController();
    bool isNull = (controller.HttpContext == null); // which is true

    //The actual HttpContext is fine in both
    bool notNull = (System.Web.HttpContext.Current == null); // which is false        

}

コントローラーのHttpContextが、System.Web.HttpContext.Currentにある "実際の" HttpContextではないことに気付きました。

コントローラーにHttpContextBaseを手動で設定する方法はありますか?または、コントローラーのインスタンスを作成するためのより良い方法はありますか?

27
Hugoware

コントローラは、あなたがしているように手動で作成するようには設計されていません。あなたが本当にすべきことは、あなたが持っている再利用可能なロジックを代わりにヘルパークラスに入れることのように思えます。

24
Brad Wilson

とりあえず、次のようにします。これは許容できる修正のようです...

public new HttpContextBase HttpContext {
    get {
        HttpContextWrapper context = 
            new HttpContextWrapper(System.Web.HttpContext.Current);
        return (HttpContextBase)context;                
    }
}

これがControllerクラスに追加される場合、これらのControllerは継承元です。

HttpContextがnullであることが望ましい動作であるかどうかはわかりませんが、これで解決されます。

61
Hugoware

ControllerContextのHttpContextは、コントローラーの作成時に設定されていないためnullです。コントローラのコンストラクタはこのプロパティを割り当てないため、nullになります。通常、HttpContextはControllerBuilderクラスのHttpContextに設定されます。コントローラは、ControllerBuilderクラスと、それに続くDefaultControllerFactoryによって作成されます。コントローラーの独自のインスタンスを作成する場合は、コントローラーのExecuteMethodを独自のControllerContextで使用できます。あなたはそれをしたくありませんそれは本当のアプリケーションです。フレームワークの経験を積むと、必要な方法が見つかります。単体テストでControllerContextが必要な場合は、モックフレームワークを使用してControllerContextをモックするか、クラスの偽装を使用できます。

リクエストフローのモデルは、asp.net mvcの このブログ にあります。

Asp.net mvcを初めて使用する場合は、ソースコードをダウンロードして、リクエストがどのように処理されるかをたどるルートのトレースを読むのは価値があります。

5
Paco

コントローラファクトリを使用していますか?もしそうなら、どのようにコンポーネントを登録していますか?

ウィンザーのトランジェントではなく、シングルトンとしてHttpContextベースの依存関係を誤って追加したときにこの問題が発生しました。

最初のリクエスト以外はすべてHttpContextがnullでした。それを突き止めるのに少し時間がかかりました。

0
Ben Scheirman

コントローラの機能を使用したいですか?または、コントローラにアクションを実行させますか?

前者の場合は、別のクラスに分割する必要があるコードかもしれません。後者の場合は、これを実行して、そのコントローラーに特定のアクションを実行させることができます。


return RedirectToAction("SomeAction", "SomeOtherController", new {param1 = "Something" });
0
mmacaulay