この記事は、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 を使ってみる (インデックス)
「ASP.NET MVC 3 で jQuery Mobile を使ってみる(その4)」への2件のフィードバック