以前、ASP.NET MVC4 Developer Preview機能の検証でこちら(【日本語訳】ASP.NET MVC4 Mobile Features Part3 Viewの新機能)のエントリーを公開しました。その際、Android用のViewを作成したのですが、実機のAndroidでアクセスしてもモバイルデバイスとは判定されませんでした。あの時はとりあえずチュートリアルを消化していくことが目的だったので深くは踏み込んでいませんが、ASP.NET4の目玉の新機能がなぜ正しく動作しなかったのかを検証していきます。
前々回のエントリーでは「Viewのオーバーライド」、前回のエントリーでは「ViewSwitcher」を対象にしました。そして残った課題がこの2つです。
- Androidがモバイル端末と判断されず、ViewSwitcherが表示されない
- cshtmlの拡張子を変更後再度拡張子をcshtmlに戻すと、そのファイルが発行対象にならなくなる?
Androidがモバイル端末と判断されない
ASP.NETはiOSはモバイル端末だと判断しますが、Androidはモバイル端末と判断しません。それでは、ASP.NETはリクエストを受けたクライアントの端末がモバイル端末かどうかをどのように判断しているのでしょうか。はい、「ブラウザ定義ファイル(Browser Definition File)」を使用しています。このブラウザ定義ファイルには、ブラウザバージョン、JavsScript,Cookieのサポート、モバイルブラウザかどうかなどのブラウザ定義情報を保持しています。そして、ASP.NETがリクエストヘッダー情報とこのブラウザ定義ファイルを利用して、リクエストがあったブラウザの情報を取得しています。
以下のディレクトリに拡張子「browser」のファイルがあり、これらのファイルがブラウザ定義と呼ばれています。
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\Browsers
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config\Browsers
また、ブラウザ定義は階層構造になっています。
「Use ASP.NET 4 Browser Definitions with ASP.NET 3.5」より抜粋
リクエストヘッダーとこのブラウザ定義ファイルから取得した情報は、System.Web.HttpRequest.Browserの各種プロパティから取得することができます。ソース(Index.cshtml, Index.Mobile.cshtml)を以下のように書き換えて、画面にブラウザ情報を表示させてみます。
<h3>This is a page for Mobile<br /> @Request.UserAgent<br /> @Request.Browser.IsMobileDevice.ToString()<br /> Type: @Request.Browser.Type<br /> Id: @Request.Browser.Id<br /> Browser: @Request.Browser.Browser<br /> MobileDeviceModel: @Request.Browser.MobileDeviceModel </h3>
それでは実行します。
Android 2.3(sh-12c)
iOS5(iPod touch)
う~ん、よく分からない...TypeやIdがどこから取得されているのか、ブラウザ定義ファイルの内容を細かく確認していないので幾つかの値を画面に出してみたんですがよく分からない...Android用のブラウザ定義ファイルが存在しないので、Safariからのアクセスと判断されてしまいモバイルデバイスと判断されていないんだと思います。
現時点でうまくいっていない内容をまとめると
- Androidからアクセスした場合に、IsMobileDeviceプロパティがFalseになりViewSwitcherが表示されない
です。これに対する対応の選択肢を考えてみると
- 現状存在しないAndroid用のブラウザ定義ファイルを作成する
- 「_ViewSwitcher.cshtml」を変更してAndroidをモバイルデバイスと判断されるようにする
本来は前者の対応をすべきだと思いますがどのように行えばいいのか分からないので、_ViewSwitcher.cshtmlを無理矢理変更して対応しようと思います。_ViewSwitcher.cshtmlのソースは以下のようになっています。
@if (Request.Browser.IsMobileDevice && Request.HttpMethod == "GET") { <div class="view-switcher ui-bar-a"> @if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice) { @: Displaying mobile view @Html.ActionLink("Desktop view", "SwitchView", "ViewSwitcher", new { mobile = false, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" }) } else { @: Displaying desktop view @Html.ActionLink("Mobile view", "SwitchView", "ViewSwitcher", new { mobile = true, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" }) } </div> }
「Request.Browser.IsMobileDevice」が正しく判断されないので、IsMobileDeviceではなくUserAgent文字列から判断させるようにします。変更したソースは以下のとおりです。
@if(Request.UserAgent.IndexOf("Android", StringComparison.OrdinalIgnoreCase) >= 0 || Request.UserAgent.IndexOf("iPhone", StringComparison.OrdinalIgnoreCase) >= 0) { <div class="view-switcher ui-bar-a"> @if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice) { @: Displaying mobile view @Html.ActionLink("Desktop view", "SwitchView", "ViewSwitcher", new { mobile = false, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" }) } else { @: Displaying desktop view @Html.ActionLink("Mobile view", "SwitchView", "ViewSwitcher", new { mobile = true, returnUrl = Request.Url.PathAndQuery }, new { rel = "external" }) } </div> }
Global.asax.csにも同様の処理を記載しているので冗長になってしまいますが、これでAndroidにもViewSwitcherが表示されるはずです。では、アクセスしてみます。
Android 2.3 (sh-12c)
iOS5 (iPod touch)
はい、無事AndroidにもViewSwitcherが表示されました。
まとめ
- ASP.NETにはAndroid用のブラウザ定義ファイルが存在しないため、モバイル用デバイスと判断されない。そのため、ViewSwitcherが表示されない。
- Androidをモバイルデバイスと判断させるためには、Android用のブラウザ定義ファイルを追加するか、_ViewSwitcher.cshtmlのロジックを書き換える必要がある。
今回作成したソースはこちらにアップします、「MVC4DPMobileDeviceCloud_3.zip」をダウンロードしてください。次回は、なぜか一部のcshtmlファイルがアップロードされなかった現象について検証を行います。