ASP.NET MVC 3 で jQuery Mobile を使ってみる(その4)

この記事は、jQuery Mobile を現時点の MVC 3 で使おうとするとどうなるかな、という興味から始めてみたものです。前回の記事でサービス系とヘルパー系について書いた記事の続きになります。

コードに入る前に、テスト方法を。どんな感じに表示されるかを見るには、エミュレータで確認するのがお手軽です。以前の記事でエミュレータについて触れているので、エミュレータが手元にない方は参考にしてください。出力される HTML のソースを確認をする方法としては、Google Chrome でユーザーエージェントを偽装させてページを表示し、右クリックで表示されるメニューから「ページのソースを表示」でページのソースを表示させるのが一番簡単だと思います。なお、jQuery Mobile が加工した後の DOM ツリーを確認したいときには、右クリックで表示されるメニューから「要素を検証」で表示させることができます。Google Chrome のユーザーエージェントの偽装方法は、ぺんたん info さんのところの記事を参考にどうぞ。

あと、jQuery Mobile を使うときの注意点があります。普段どおりに HTTP POST の処理をしたあとにリダイレクトをすると、スマートフォン側でリロードが行われるとリダイレクト前の URL でページ表示が行われてしまいます 😥 どうなっているのかを確認するために偽装した Google Chrome で表示させると、リダイレクト前後でアドレスバーに表示される URL が変わっていません 😯 解決策を書いてるところはないかなぁと検索してみると、griefworker さんのところの記事がヒットしました。リダイレクトするときには「data-role=”page” を指定したタグに、data-url=”ページのURL” も指定する必要がある。」と書かれています。HTML ファイルを個別に作っていればすぐに対応できますが、ASP.NET MVC だと Shared\_Layout.cshtml をビューで読み込んで合成していて、「data-role=”page”」の設定は _Layout.cshtml 側になります。

これに対応するために、個別のアクションで ViewBag に URL 情報をセットして、_Layout.Mobile.cshtml 側で ViewBag からデータを読み取り data-url にセットするようにしました。

それでは作成の話に戻ります。

コントローラー

コントローラーは「HomeController.cs」「BookController.cs」の2つです。
コードを見ていただければ分かりますが、表示するビューの名称を (その3) で作成した MobileHelper.GetViewName メソッドで取得するようにしています。また、HomeController のほうではリダイレクトがないので、ViewBag への URL 情報のセットは行なっていません。

HomeController.cs

using System.Web.Mvc;
using GetExternalXml001.Helpers;

namespace GetExternalXml001.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "新刊案内";

            var viewName = MobileHelper.GetViewName(this.ControllerContext);
            return View(viewName);
        }

        public ActionResult About()
        {
            var viewName = MobileHelper.GetViewName(this.ControllerContext);
            return View(viewName);
        }
    }
}

BookController.cs

using System.Web.Mvc;
using GetExternalXml001.Helpers;
using GetExternalXml001.Models;
using GetExternalXml001.Services;

namespace GetExternalXml001.Controllers
{
    public class BookController : Controller
    {
        private IBookService _service;

        public BookController()
        {
            _service = new BookService();
        }

        //
        // GET: /Book/

        public ActionResult Index()
        {
            _service.GetBooksByRss();
            var books = _service.FindBooks();

            var viewName = MobileHelper.GetViewName(this.ControllerContext);
            ViewBag.DataUrl = "/Book";
            return View(viewName, books);
        }

        //
        // GET: Details/2

        public ActionResult Details(int id)
        {
            var book = _service.GetBook(id);

            if (book == null)
            {
                TempData["message"] = "取得データが期限切れとなったためデータを取り直しました。";
                return RedirectToAction("Index");
            }

            var viewName = MobileHelper.GetViewName(this.ControllerContext);
            ViewBag.DataUrl = "/Book/Details/" + book.Id;
            return View(viewName, book);
        }

        //
        // GET: SendNotice/2

        public ActionResult SendNotice(int id)
        {
            var book = _service.GetBook(id);

            if (book == null)
            {
                TempData["message"] = "取得データが期限切れとなったためデータを取り直しました。";
                return RedirectToAction("Index");
            }

            var viewName = MobileHelper.GetViewName(this.ControllerContext);
            ViewBag.DataUrl = "/Book/SendNotice/" + book.Id;
            return View(viewName, new NoticeInfo {
                MailAddress = "",
                Id = book.Id,
                Title = book.Title,
                Url = book.Link
            });
        }

        //
        // POST: SendNotice

        [HttpPost]
        public ActionResult SendNotice(NoticeInfo noticeInfo)
        {
            // 本来のバリデーションは実装しません。中に'@'があるかだけ
            if (!string.IsNullOrEmpty(noticeInfo.MailAddress) &&
                !noticeInfo.MailAddress.Contains("@"))
            {
                ModelState.AddModelError("MailAddress", "メールアドレスが誤っています。");
            }

            if (!ModelState.IsValid)
            {
                var viewName = MobileHelper.GetViewName(this.ControllerContext);
                ViewBag.DataUrl = "/Book/SendNotice/" + noticeInfo.Id;
                return View(viewName, noticeInfo);
            }

            /* メール送信機能は実装しません */

            TempData["message"] = "新刊情報をメール送信したつもり。";
            return RedirectToAction("Index");
        }
    }
}

リダイレクト先で通知メッセージを表示させるために、System.Web.Mvc.ControllerBase.TempData プロパティを使っています。

あと残っているのはビュー関係ですが、長くなるので「その5」に書くことにします。


ASP.NET MVC 3 で jQuery Mobile を使ってみる (インデックス)


2 thoughts on “ASP.NET MVC 3 で jQuery Mobile を使ってみる(その4)

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です