前回の記事では、Ajax 通信でページを部分更新する際の例外処理について記載しましたが、それに関連した内容です。
ASP.NET MVC 5 の Ajax 通信で PartialView を返す際に、JSON の一部として返したいケースがありました。例外処理と似たような感じで、Exception が発生した際にエラーページに遷移するのではなく、メッセージボックスで通知したいシナリオです。元ネタの実装とほとんど同じなのですが、自分なりに整理してみました。
ベースとなる抽象コントローラークラスを用意して、PartialView を含む JSON を返すヘルパーメソッドを実装します。部分ビュー名、バインドするモデル、エラーメッセージを受け取って、JsonResult を返します。
#MyBaseController.cs public abstract class MyBaseController : Controller { protected JsonResult PartialViewAsJson(string viewName) { return PartialViewAsJson(viewName, null, null); } protected JsonResult PartialViewAsJson(string viewName, string exceptionMessage) { return PartialViewAsJson(viewName, null, exceptionMessage); } protected JsonResult PartialViewAsJson(string viewName, object model) { return PartialViewAsJson(viewName, model, null); } protected JsonResult PartialViewAsJson(string viewName, object model, string exceptionMessage) { ViewData.Model = model; var viewAsString = ""; using (var sw = new StringWriter()) { var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); viewResult.View.Render(viewContext, sw); viewAsString = sw.GetStringBuilder().ToString(); } return Json(new { partialView = viewAsString, message = exceptionMessage }); } }
MyBaseController クラスを継承した HomeController クラスでは、PartialView ヘルパーメソッドではなく、上記で実装した PartialViewAsJson ヘルパーメソッドで ActionResult を返します。
#HomeController.cs public class HomeController : MyBaseController { [HttpPost] public ActionResult AjaxTest() { if (Request.IsAjaxRequest()) { try { return PartialViewAsJson(viewName: "_AjaxResult"); } catch (Exception ex) { return PartialViewAsJson(viewName: "_AjaxResult", exceptionMessage: ex.Message); } } return Content("Ajax 通信以外のアクセスはできません。"); } }
ビューでは、 Ajax 通信のレスポンスの JSON を受け取り、エラーメッセージがあれば alert を表示し、なければ部分ビューを表示します。
#Ajax.cshtml @section Scripts { @Scripts.Render("~/bundles/jqueryval") <script> $(function () { $('#test').click(function () { $.ajax({ type: 'POST', url: 'AjaxTest' }) .done(function (data, textStatus, jqXHR) { if (data.message != null) { alert(data.message); } else { $('#ajax-result').html(data.partialView); } }) .fail(function (jqXHR, textStatus, errorThrown) { if (jqXHR.status == 401) { $(location).attr("href", "/Account/Login/"); } else { $(location).attr("href", "/Error/AjaxError/"); } }); }) }) </script> }
Ajax 通信のレスポンスでは、次のような JSON が返されていることが確認できます。
まとめ
ASP.NET MVC で、デスクトップアプリケーションに似たデザインの UI を作るとなると、Ajax 通信でページを部分更新するケースは多くなります。その際に、JSON の一部として PartialView を返すことができると、意外と便利なケースがあるのではないかと思います。