この方法の欠点としては別の 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 を使って確認してみました。まずは日本語とスマートフォンの組み合わせです。
意図したとおりに表示されていますね。次は英語とスマートフォンの組み合わせです。
こちらも意図したとおりに表示されました。
今回作成した CompositeDisplayMode を使えば、いろんな Display Mode を作成して、それを組み合わせて使うことが出来るので便利かもしれません。