WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

ASP.NET Core MVC と Ajax ライブラリ

by WebSurfer 6. March 2020 21:10

.NET Framework の ASP.NET MVC5 アプリケーションでは AjaxHelper(Ajax.BeginForm, Ajax.ActionLink など)と Microsoft の Ajax ライブラリ jquery.unobtrusive-ajax.js を利用して、Ajax で部分ビューを呼び出してページ内の指定の場所に表示するなどのことが、JavaScript / jQuery のコードを書かなくても容易にできるようになっています。

Ajax で部分ビューを表示

同じことが ASP.NET Core 3.1 MVC でもできるだろうと思っていましたがダメでした。

MVC5 であれば、先の記事「MVC5 で AjaxHelper が働かない」で書きましたように NuGet から Microsoft.jQuery.Unobtrusive.Ajax をインストールすれば、AjaxHelper を使って目的が果たせます。

ところが、ASP.NET Core 3.1 MVC では、まず AjaxHelper が使えないようです。また、NuGet で Microsoft.jQuery.Unobtrusive.Ajax をインストールしても、肝心の jquery.unobtrusive-ajax.js が wwwroot に配置されません。(LibMan を使えということのようですが jquery.unobtrusive-ajax.js は登録されてないようです)

そこを無理やり(?) jquery.unobtrusive-ajax.js を使って Ajax で部分ビューを呼び出してページ内の指定の場所に表示するにはどうするかを以下に書きます。

(1) まず、jquery.unobtrusive-ajax.js を入手して以下の画像のように wwwroot 下のフォルダに配置します。

jquery.unobtrusive-ajax.js を配置

(2) 外部スクリプトファイル jQuery.js と上記 (1) の jquery.unobtrusive-ajax.js がダウンロードされるよう、View に script 要素を設定します。必ず jQuery.js が先に来るようにしてください。

_Layout.cshtml を使っていれば jQuery.js は設定されるようになっているので、View には jquery.unobtrusive-ajax.js だけ追加されるように設定すれば良いはずです。

(3) View のコードの form 要素に以下の属性を追加します。

data-ajax="true" data-ajax-mode="replace" data-ajax-update="#result"

その意味は jquery.unobtrusive-ajax.js を使って ajax で要求を出し、返ってきた応答で id が result の要素の中身を書き換えるということです。属性の説明については以下の記事が詳しいので参考にしてください。

Using jQuery Unobtrusive AJAX in ASP.NET Core Razor Pages

Controller と View のサンプルコードを以下に書いておきます。使っているのは Microsoft が提供する Northwind サンプルデータベースの Customers テーブルです。

その CompanyName をドロップダウンリストに表示し、ユーザーが選択してボタンをクリックすると指定した Customers のレコードの詳細を、部分ビューを呼び出して、それを指定した場所(下の View のコードで言うと <div id="result"></div> の中)に書き出すものです。

Controller / Action Method

using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;

namespace MvcCoreApp.Controllers
{
  public class AjaxController : Controller
  {
    private readonly NorthwindContext _context;

    public AjaxController(NorthwindContext context)
    {
      _context = context;
    }

    // jquery.unobtrusive-ajax.js の助けを借りて
    // 部分ビューで詳細 Customer データを表示
    public IActionResult Index()
    {
      // 全部取得すると長すぎるので Take(10) した
      var list = _context.Customers.Take(10);
      ViewData["customers"] =
        new SelectList(list, "CustomerId", "CompanyName");
      return View();
    }

    // 部分ビュー用のアクションメソッド
    [HttpPost]
    [ValidateAntiForgeryToken]
    public IActionResult Details(string customerid)
    {
      if (string.IsNullOrEmpty(customerid))
      {
        return NotFound();
      }

      var customer = _context.Customers.Find(customerid);

      if (customer == null)
      {
        return NotFound();
      }

      return PartialView(customer);
    }
  }
}

View (Index.cshtml)

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<form asp-action="Details" asp-controller="Ajax" 
      data-ajax="true" data-ajax-mode="replace" 
      data-ajax-update="#result" method="post">

    <select id="customerid" name="customerid" 
            asp-items="@ViewBag.customers">
    </select>

    <input type="submit" value="詳細表示" />

</form>

<div id="result"></div>

@section Scripts {
  <script src="...フォルダ.../jquery.unobtrusive-ajax.js">
  </script>

部分ビュー (Details.shtml)

@model MvcCoreApp.Customers

<div>
    <dl class="row">
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.CustomerId)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.CustomerId)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.CompanyName)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.CompanyName)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.ContactName)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.ContactName)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.ContactTitle)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.ContactTitle)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Address)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Address)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.City)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.City)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Region)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Region)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.PostalCode)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.PostalCode)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Country)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Country)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Phone)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Phone)
        </dd>
        <dt class = "col-sm-2">
            @Html.DisplayNameFor(model => model.Fax)
        </dt>
        <dd class = "col-sm-10">
            @Html.DisplayFor(model => model.Fax)
        </dd>
    </dl>
</div>

jquery.unobtrusive-ajax.js は ASP.NET Core MVC ではサポートされてないような気がしますが、上記のようにすれば一応使えます。

jquery.unobtrusive-ajax.js を使わなくても同等のことは jQuery ajax を使ってできます。それについては別の記事「jQuery ajax で部分ビューの呼出・表示」を見てください。

Tags: , , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  March 2020  >>
MoTuWeThFrSaSu
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345

View posts in large calendar