WebSurfer's Home

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.cshtml)

@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

ASP.NET Core MVC の Bundle と Minify

by WebSurfer 6. February 2020 15:49

ASP.NET Core 3.1 MVC で .css ファイルと .js ファイルをバンドル&ミニファイする機能を実装しようとしてハマった話を書きます。

Bundle と Minify

手順は Microsoft のドキュメント Bundle and minify static assets in ASP.NET Core に詳しく書いてあります。

2022/5/31 追記: いつの間にか上に紹介した Microsoft ドキュメントからは以下に書いた手順は削除されていますが、Visual Studio 2022 で作った .NET 6.0 プロジェクトでも有効なのは確認しました。

ドキュメントにはいろいろ書いてありますが、ビルド時にバンドル&ミニファイ版の .css ファイル、.js ファイルを生成するなら下の (1), (2) の手順だけで可能です。

(1) Configure bundling and minification のセクションに従ってアプリケーションルートに bundleconfig.json を追加。以下にドキュメントに記載されている例を書いておきます。詳しい説明はドキュメントを読んでください。

[
  {
    "outputFileName": "wwwroot/css/site.min.css",
    "inputFiles": [
      "wwwroot/css/site.css"
    ]
  },
  {
    "outputFileName": "wwwroot/js/site.min.js",
    "inputFiles": [
      "wwwroot/js/site.js"
    ],
    "minify": {
      "enabled": true,
      "renameLocals": true
    },
    "sourceMap": false
  }
]

(2) Build-time execution of bundling and minification のセクションに従って BuildBundlerMinifier を NuGet からインストール。(BundlerMinifier.Core ではないので注意)

BuildBundlerMinifier をインストール

ここまでの設定で、Visual Studio でプロジェクトをビルドする時、bundleconfig.json の inputFiles に指定した .css, .js ファイルをバンドル&ミニファイして outputFileName に指定したパス/ファイル名で配置してくれます。一番上の画像の赤枠で囲ったファイルを見てください。

Visual Studio が自動的にやってくれるのはここまでであることに注意してください。

一番上の画像のようにバンドル&ミニファイ版のファイルを作って配置してくれるだけなので、例えば元のソースが以下のように通常版のパスを参照している場合は site.css ⇒ site.min.css、site.js ⇒ site.min.js に書き換える必要があります。ちなみに、テンプレートで自動生成される _Layput.cshtml がデフォルトで下記のようになっています。

<link rel="stylesheet" href="~/css/site.css" />
<script src="~/js/site.js"></script>

ここが Microsoft のドキュメントに書いてなくて、何故記事の通りやっているのにバンドル&ミニファイされないのか分からず、半日ぐらいハマってしまったところです。(汗)

そんなの当たり前に分かるだろうと思われるかもしれませんね。でも、.NET Framework MVC の場合は、テンプレートでプロジェクトを自動生成するだけで、web.config で <compilation debug="true" ... > と設定してある時は通常版の .css と .js ファイルが、debug="false" の時はバンドル&ミニファイ版が自動的に設定されるのです。

自分は Core MVC でも .NET Framework MVC と同様に、そこまで面倒見てくれると思い込んでいたので気が付きませんでした。(涙)

Tags: , , ,

CORE

ASP.NET Core 3

by WebSurfer 15. December 2019 20:53

ASP.NET Core 3 の本

ASP.NET Core の勉強を始めようと思って左の画像の本を買って PC に Visual Studio Community 2019 をインストールしました。

自分が今まで使ってきた Visual Studio 2015 にはすでに ASP.NET Core の開発環境が提供されていたのですが、先の記事に書いた「ASP.NET Core で文字化け」という問題があったのです。

まだ枯れてないフレームワークには他にもいろいろ不具合がありそうな気がしましたし、勉強を始めたはいいが途中で開発中止になってしまう可能性もないわけではありませんでしたし、手を出すのは時期尚早と思ってました。(言い訳です(笑))

どうやら開発中止になるどころか Microsoft も Core への移行を推奨するそうですし、2019 年 11 月にバージョン 3.1 がリリースされて安定してきたそうなので、時代に取り残されてはいけないと思って本を買ってきた次第です。

実は、上に紹介した時事を書いた頃少しだけ勉強したのですが、サーバー周りが旧来の ASP.NET とは大幅に異なっていて、今の知識が役に立たなそうなのにビビってました。

Model, View, Controller のコードの基本的なところにはそんなに違いはないようですが、それでもやはり従来の MVC の知識が通用しないところがありそうです。

.NET Framework ベースの ASP.NET の知識も十分とは言えない自分が余計なものに手を出すべきではないのかもしれません。

でも、ソフト開発でメシを食っているわけではない自分にとっては所詮趣味の問題に過ぎないので、自己満足できればいいと思うことにします。(笑)

Tags:

CORE

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。ブログ2はそれ以外の日々の出来事などのトピックスになっています。

Calendar

<<  July 2025  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar