2015年7月3日

非同期 ASP.NET MVC と HttpContext.Current

非同期な ASP.NET MVC で HttpContext.Current を使うのはやめた方がいい、という話。

[非同期メソッドのサンプル]

public class MyController : Controller
{
    // RouteConfig で URL が割り当てられた非同期メソッド
    public async Task<ActionResult> Test()
    {
        // (A)

        await Task.Run(() => {
            // (B)
        });

        // (C)

        return View();
    }
}

上記で HttpContext.Current が使用できるのは (A) (B) (C) のどこか?
と疑問になったので調査してみた。

[結果]
(A) 使用可能
(B) 使用不可
(C) web.config の設定で変わる
<appSettings><add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> を設定、または、<system.web><httpRuntime targetFramework="4.5"> (4.5 以上なら OK) を設定すると使用可能
上記を設定してない場合は使用不可
※ Windows 7/IIS 7.5/ASP.NET MVC 5/.NET 4.5.2
※ Visual Studio 付属の IIS Express は異なる結果になる場合あり

ちなみに、真ん中の Task を ConfigureAwait(false) とすると、設定に関わらず (C) でも HttpContext.Current 使用不可。

まとめ

調査結果のとおりなのだが、非同期だと HttpContext.Current は設定やコードに依存して使えたり使えなかったりするので、使わない方がまし・・・使用禁止でもいいと思う。

そもそも ASP.NET MVC の Controller クラスには HttpContext プロパティがあるので、これを使うのが普通。
Controller から呼び出すロジッククラスでは、HttpContext を引数渡しで使うのが無難。コードが増えるけど・・・
当たり前だけど HttpContext クラスにできるだけ依存しないクラス設計が大事。

参考URL