しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

ASP.NET MVC 4 で現在の Display Mode を取得する

ASP.NET MVC 4 というか Web Pages で追加された Display Mode を使うと条件を少し書くだけで、いろんなデバイス向けのビューに切り替えたりできて便利ですね。おかげでコントローラ側でデバイスを意識することなく書けるようになりました。

しかし、世の中にはコントローラでモバイルデバイスなのかそれ以外なのか知りたいときもあります。そういう時にはどうしようという話なんですが、せっかく Display Mode で UA の判別などを行っているので、その結果だけ頂こうと思います。

ちょっと調べたところ、ControllerContext が現在の Display Mode を保持しているようです。これが使えそうですね。

public ActionResult Index()
{
    // 現在の DisplayMode を取得する?
    var displayMode = ControllerContext.DisplayMode;

    return View();
}

しかし、実際に実行してみると DisplayMode が null になっています。どうやらビューが表示される直前に設定されるので、アクションの内部では使えないようです。

仕方ないので ASP.NET MVC 4 のソースコードを追って、どのように Display Mode を決定しているのか調べてみると DisplayModeProvider クラスの GetAvailableDisplayModesForContext メソッドを使って決定しているようでした。*1

var displayModes = DisplayModeProvider.Instance.GetAvailableDisplayModesForContext(ControllerContext.HttpContext, ControllerContext.DisplayMode);

これで条件にマッチする DisplayMode が取得できますが、複数返ってくることもあるので最初の値を使うようにします。これらの処理を拡張メソッドとしたものが以下のコードになります。

public static class DisplayModeProviderExtension
{
    public static string GetCurrentDisplayModeId(this ControllerContext controllerContext)
    {
        var displayMode = DisplayModeProvider.Instance.GetAvailableDisplayModesForContext(controllerContext.HttpContext, controllerContext.DisplayMode).FirstOrDefault();

        if (displayMode == null)
        {
            return null;
        }

        return displayMode.DisplayModeId;
    }
}

この拡張メソッドを使うことで、以下のようにすっきりと取得することが出来るようになりました。

public ActionResult Index()
{
    if (ControllerContext.GetCurrentDisplayModeId() == "iPhone")
    {
        // iPhone の場合
    }

    return View();
}

本来ならばコントローラにビューに依存するコードを入れたくはないんですが、実際に仕事となるとそうは言ってられないのが悩みどころです。

*1:実際にはビューが存在しているかも考慮するが、今回は必要ない