読者です 読者をやめる 読者になる 読者になる

しばやん雑記

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

ASP.NET MVC 4 で複数の Display Mode を組み合わせて使ってみる

この方法の欠点としては別の Display Mode との共存が出来ないことです。なのでスマートフォンへの対応が必要ない、完全に PC 向けのページなら対応可能かと思います。

ASP.NET MVC 4 の Display Mode を使って多言語対応を試してみた - しばやん雑記

と書いたんですが、複数の Display Mode を組み合わせて 1 つの Display Mode として扱えば解決できるんじゃないかと思ったので、以下のような CompositeDisplayMode クラスを実装して試してみました。

public class CompositeDisplayMode : IDisplayMode
{
    public CompositeDisplayMode(IEnumerable<IDisplayMode> modes)
    {
        _modes = modes;
    }

    private readonly IEnumerable<IDisplayMode> _modes;

    public bool CanHandleContext(HttpContextBase httpContext)
    {
        return _modes.Any(p => p.CanHandleContext(httpContext));
    }

    public DisplayInfo GetDisplayInfo(HttpContextBase httpContext, string virtualPath, Func<string, bool> virtualPathExists)
    {
        var transformedFilename = virtualPath;

        foreach (var displayMode in _modes.Where(p => p.CanHandleContext(httpContext)))
        {
            var displayInfo = displayMode.GetDisplayInfo(httpContext, transformedFilename, virtualPathExists);

            if (displayInfo != null)
            {
                transformedFilename = displayInfo.FilePath;
            }
        }

        if (transformedFilename != virtualPath)
        {
            return new DisplayInfo(transformedFilename, this);
        }

        return null;
    }

    public string DisplayModeId { get { return "Composite"; } }
}

単純に IDisplayMode のコレクションを内部で保持して、仮想パスを変換していくだけのクラスです。

実際に使う時には、Global.asax.cs などに以下のように設定を書きます。

DisplayModeProvider.Instance.Modes.Insert(0, new CompositeDisplayMode(new IDisplayMode[]
{
    new LocalizableDisplayMode(),
    new DefaultDisplayMode(DisplayModeProvider.MobileDisplayModeId)
    {
        ContextCondition = context => context.GetOverriddenBrowser().IsMobileDevice
    }
}));

処理の優先順位としては登録した順番なので、まずは前回作成した多言語対応の Display Mode が処理されてから、スマートフォン対応の Display Mode が処理されるようになっています。

つまり、以下のようなビューを定義することになります。

  • Index.cshtml
    • デフォルトのビュー
  • Index.Mobile.cshtml
    • デフォルトのスマホ向けビュー
  • Index.ja-JP.cshtml
    • 日本語のビュー
  • Index.ja-JP.Mobile.cshtml
    • 日本語のスマホ向けビュー

実際に Google Chrome と Fire Mobile Simulator を使って確認してみました。まずは日本語とスマートフォンの組み合わせです。

f:id:shiba-yan:20130531130243p:plain

意図したとおりに表示されていますね。次は英語とスマートフォンの組み合わせです。

f:id:shiba-yan:20130531130821p:plain

こちらも意図したとおりに表示されました。

今回作成した CompositeDisplayMode を使えば、いろんな Display Mode を作成して、それを組み合わせて使うことが出来るので便利かもしれません。