WebSurfer's Home

トップ > Blog 1   |   ログイン
APMLフィルター

スキャフォールディング機能 (CORE)

by WebSurfer 2020年3月16日 14:47

ASP.NET Core 3.1 MVC プロジェクトで、既存のデータベースからコンテキストクラスとテーブルクラスを生成し、それをベースに Visual Studio 2019 のスキャフォールディング機能を使って Create, Read, Update, Delete (CRUD) 操作を行うための Controller と View を自動生成する手順を書きます。

Create

先の記事「スキャフォールディング機能」で .NET Framework MVC5 プロジェクトのケースを紹介しましたが、今回の記事はそれと同等なことを ASP.NET Core 3.1 MVC プロジェクトで行うものです。

上の画像は作成した ASP.NET Core 3.1 MVC アプリの編集 (Create) 画面を Edge から呼び出して表示したものです。(理由不明ですが一部の項目のコードが生成されていません。Create 以外は OK)

先の MVC5 の記事と同様、この記事でも既存のデータベースとして Microsoft のサンプルデータベース Northwind を使用し、その中の Products テーブルの CRUD 操作を行うことにします。

大まかな手順は以下の通りです。

  1. SQL Server にサンプルデータベース Northwind をアタッチして接続できるようにしておく。
  2. Visual Studio Community 2019 のテンプレートを使用して ASP.NET Core 3.1 MVC プロジェクトを生成。
  3. リバースエンジニアリングによって Northwind データベースからコンテキストクラスとテーブルクラスを生成してプロジェクトに追加する。(EF Core では Visual Studio の ADO.NET Entity Data Model のウィザードで EDM を作るということはできません)
  4. 追加したコンテキストクラスとテーブルクラスをベースに、スキャフォールディング機能を使って CRUD 操作用の Controller と View を自動生成する。

以下に、Visual Studio で上の操作を行った際に表示された画像を貼って要点を書いておきます。

(1) リバースエンジニアリング

リバースエンジニアリング

Visual Studio のパッケージマネージャーコンソールで、Microsoft ドキュメント「リバースエンジニアリング」を参考に、既存の SQL Server データベース Northwind からコンテキストクラスとテーブルクラスを生成します。(各パラメータについては、こちらの記事 Scaffold-DbContext の方がまとまっていてわかりやすいかも)

パラメータの内 -Connection と -Provider の設定は必須です。

-Connection に設定する接続文字列ですが、文字列に空白がある場合(普通あるはず)は接続文字列全体をクォーテーション " で囲います。バックスラッシュ \ はエスケープする必要はありません。上の画像を見てください。

-Provider に設定するプロバイダ名は、SQL Server を使っている場合は Microsoft.EntityFrameworkCore.SqlServer とします。

その他のパラメータ設定はオプションです。上の画像の例では -ContextDir でコンテキストクラスを生成するディレクトリ、-OutputDir でテーブルクラスを生成するディレクトリ、-Tables で含めるテーブルの名前(今回は Products, Categories, Suppliers を指定)、-DataAnnotations で各プロパティにデータアノテーション属性を付与するように指定しています。

成功すると Build succeeded. と表示されます。

(2) 生成されたクラス

生成されたクラス

リバースエンジニアリングの結果、上のステップ (1) のパラメータで指定した通り DAL ディレクトリにコンテキストクラス NorthwindContext.cs、Models ディレクトリにテーブルクラス Products.cs, Categories.cs, Suppliers.cs が生成されています。

(3) スキャフォールディング

スキャフォールディング

Visual Studio のソリューションエクスプローラーで Controllers を右クリックして[追加(D)]⇒[コントローラー(T)...]⇒[新規スキャフォールディングアイテムの追加]⇒[Entity Framework を使用したビューがある MVC コントローラー]と進んで、出てきたダイアログでスキャフォールディングの設定を行います。

この記事では、モデルクラス(M) には CRUD 対象とする SQL Server のテーブルに対応する Products クラスを、データコンテキストクラス(D) には NorthwindContext.cs の NorthwindContext クラスを設定しています。

[追加]ボタンをクリックすると SQL Server の Products テーブルの CRUD に必要な Controller / Action Methods と View が一式自動生成されます。

(4) コードの変更・追加

この状態で実行すると "InvalidOperationException: Unable to resolve service for type 'NorthwindContext' while attempting to activate 'ProductsController'" というエラーになるはずです。

なので、Code First で作った時と同様な形になるよう、以下の変更・追加を行います。

  1. 接続文字列を appsettings.json に追加。JSON 形式で名前は "NorthwindConnection" とし、値はステップ (1) で設定したものと同じにします。なお、JSON 文字列なので \ はエスケープして \\ にする必要があることに注意してください。
  2. NorthwindContext.cs の NorthwindContext クラスに自動生成されているコードの中から、引数を取らないコンストラクタ NorthwindContext() をコメントアウト。
  3. ProductsController に NorthwindContext オブジェクトを DI できるよう、Startup.cs の ConfigureServices メソッドに services.AddDbContext<NorthwindContext>( ... ) を追加。

上記 1 ~ 3 の変更・追加の後アプリを実行すれば期待通り動きます。

但し、理由は不明ですが、スキャフォールディン機能で自動生成された Create.cshtml には項目 UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel のコードがありません。そこはだけは自力でコードを書く必要がありました。

上記ステップ (3) のスキャフォールディング前に、ステップ (4) のコードの変更・追加をしないとダメかもと思い、(3), (4) の順序を逆にして試してみましたが結果は同じでした。

その他の View、Index.cshtml, Delete.cshtml, Details.cshtml, Edit.cshtml には全項目のコードが生成されていました。

Tags: , , ,

CORE

スキャフォールディング機能

by WebSurfer 2017年7月23日 18:41

既存のデータベースから Entity Data Model (EDM) を作り、スキャフォールディング機能を使って Create, Read, Update, Delete (CRUD) 操作を行うための ASP.NET MVC アプリを作る手順を備忘録として書いておきます。

完成した Crate 画面

上の画面は作成した ASP.NET MVC アプリの編集 (Create) 画面を IE11 から呼び出して表示したものです。

この記事では、既存のデータベースとして Microsoft のサンプルデータベース Northwind を使用し、その中の Products テーブルの CRUD 操作を行うことにします。

大まかな手順は以下の通りです。

  1. SQL Server にサンプルデータベース Northwind をアタッチして接続できるようにしておく。(LocalDB も使えます。詳しくは先の記事「LocalDB で Northwind と Pubs を利用」を参照)
  2. Visual Studio Community 2015 のテンプレートを使用して ASP.NET MVC5 プロジェクトを生成。
  3. Visual Studio のデザイナを利用して、Northwind データベースから EDM を生成してプロジェクトに追加する。
  4. 追加した EDM をベースに、スキャフォールディング機能を使って CRUD 操作用の Controller と View を自動生成する。

以下に、Visual Studio で上の操作を行った際に表示された画像を貼って要点を書いておきます。自力では一行もコードを書くことなく CRUD 操作が可能な ASP.NET MVC アプリを自動生成できます。

(1) 新しい項目の追加

新しい項目の追加

プロジェクトに EDM を追加するため、ソリューションエクスプローラーでプロジェクトノードを右クリック⇒[追加(D)]⇒[新しい項目(W)...]をクリック。

(2) ADO.NET Entity Data Model を選択

ADO.NET Entity Data Model を選択

表示された「新しい項目の追加」ダイアログで[ADO.NET Entity Data Model]を選択し[追加(A)]をクリック。

(3) モデルのコンテンツの選択

モデルのコンテンツの選択

既存の SQL Server データベースから EDM を生成するため、[データベースから EF Designer]を選択し[次へ(N)]をクリック。

(4) データ接続の選択

データ接続

接続先の SQL Server データベースの指定、接続文字列等の設定を行うため[新しい接続(C)...]をクリック。

(注:上の画像で DefaultConnection というのは Visual Studio のテンプレートでプロジェクトを生成した時に自動的に設定される ASP.NET Identity 用のユーザー情報のストアに使用されるデータベースです)

(5) 接続のプロパティ設定

接続のプロパティ設定

自分の環境では MySQL がデフォルトで選択されているので、これを SQL Server に変更するため[変更(C)...]をクリック。デフォルトで SQL Server が選択されていれば不要な操作です。

(6) データソースの変更

データソースの変更

今回は SQL Server の既定の(または名前付き)インスタンスに接続するため[Microsoft SQL Server]を選択します。

(7) 接続のプロパティ設定

接続のプロパティ設定

[サーバー名(E)]にサーバー名を入力すると[データベース名の選択または入力(D)]にアタッチ済みのデーターベース一覧が表示されるので、その中から Northwind を選択し[OK]ボタンをクリック。

(注:この例では開発マシンにインストールした SQL Server 2008 Express に接続しています。デフォルトでインストールしたので sqlexpress という名前の名前付きインスタンスになっています)

(8) 接続文字列の確認と web.config への保存

接続文字列の確認と web.config への保存

(4) の画面に戻るので、接続文字列とその名前を確認し[次へ(N)]ボタンをクリック。

(9) データベースオブジェクトと設定の選択

データベースオブジェクトと設定の選択

今回の例では Products テーブルの CRUD 操作を行うので[テーブル]にチェックを入れ[完了(F)]ボタンをクリック。

(10) 生成された EDM

生成された EDM

無事 EDM が生成されると上のような画面が表示されます。ソリューションエクスプローラーの .edmx ファイルの下には DbContext を継承したコンテキストクラス、データベースの各テーブルを表すモデルクラスも自動生成されます。

(11) コントローラーの追加

コントローラーの追加

スキャフォールディング機能を利用して Controller と View を MVC アプリに追加します。ソリューションエクスプローラーで Controller フォルダを右クリック⇒[追加(D)]⇒[コントローラー(T)...]をクリック。

(12) スキャフォールディングを追加

スキャフォールディングを追加

上の手順で生成した EDM をベースに Controller と View を一式生成するには[MVC 5 Controller with Views, using Entiry Framework]を選択し[追加」ボタンをクリックします。

(13) コンテキストクラス、モデルクラスの指定

コンテキストクラス、モデルクラスの指定

(10) で生成されたコンテキストクラス、モデルクラスを指定します。今回の例ではコンテキストクラスは NORTHWINDEntities クラス、モデルクラスは Products テーブルの CRUD 操作を行うので Products クラスになります。

[Add]ボタンをクリックすると Controller と View が自動生成されプロジェクトに追加されます。


以上の操作は Visual Studio 2010 で MVC4 アプリを作る場合もほぼ同じですが、生成される EDM, Controller, View はかなり進化しているようです。主な点は以下の通りです。

  1. 生成される EDM は EF6 の DbContext ベース。そのためか、Code First で作ったモデルと DB First で作ったモデルは共存可能になっている。(Visual Studio 2010 ではデフォルトで EF4 の ObjectContext ベース。Code First で作ったモデルとは同じプロジェクト内では共存不可)
  2. 一覧 (Index) 画面には CatrgoryID, SupplierID(数字)ではなく、ナビゲーションプロパティをたどって CategoryName, CompanyName を取得してそれが表示される。さらに、Linq 式に Include メソッドを使いプロパティを先読みするという配慮もされている。
  3. 新規作成 (Create)、編集 (Edit) 画面では CatrgoryID, SupplierID にドロップダウンリストを使用して CategoryName, CompanyName が表示され、ユーザーは数字ではなくそれに該当する名前を見て選択できる。
  4. View には @Html.AntiForgeryToken()、Controller のアクションメソッドには ValidateAntiForgeryToken 属性が自動的に付与される。
  5. オーバーポスティングアタック対策として引数にホワイトリスト(Bind 属性)が自動的に付与される。

Tags: ,

MVC

ASP.NET Core で文字化け

by WebSurfer 2017年6月16日 20:37

ASP.NET Core のプロジェクトで、スキャフォールディング機能を利用して生成した View に日本語を書き込むと、文字化けするという話を書きます。元の話は Teratail の記事「ASP.NET Core でスキャフォールディングすると文字化けする」です。(注: VS2015 ASP.NET Core v1 の話です。VS2019 ASP.NET Core v3.1 では直っていました)

ASP.NET Core での文字化け

上の画像で赤枠で囲った部分が問題の文字化けです。どのような理由でそうなるかを以下に説明します。

(注:何行にもわたって書き込むとサーバーエラーになり、"An error occurred during the compilation of a resource required to process this request. Please review the following specific error details and modify your source code appropriately. "�" is not valid at the start of a code block. Only identifiers, keywords, comments, "(" and "{" are valid." というエラーメッセージが出ることもあります)

検証に使った環境は以下の通りです。Visual Studio 2017 でも同じ問題が出るとのことです。

  • Visual Studio 2015 Community 2015 Update 3
  • ASP.NET Core Web Application (.NET Core) のテンプレート使用
  • Windows 10 Professional 64-bit
  • IIS 10.0 Express

そもそもの原因は、スキャフォールディング機能を利用して生成した View の文字コードが Shift_JIS になってしまうことです(日本語 OS の場合)。.NET Framework ベースの MVC プロジェクトの View はデフォルトでは BOM 付きの UTF-8 になります。それを Shift_JIS に変換しても文字化けの問題は出ません。何故か、Core では Shift_JIS では対応できず、上の画像のように文字化けします。

Fiddler を使って応答をキャプチャし、問題の文字 "�" のバイト列を調べてみたら EF BF BD となっていました。

MSDN ライブラリ「.NET で文字エンコーディング クラスを使用する方法」によると "Unicode デコーダーでは、デコードできない 2 バイトのシーケンスが REPLACEMENT_CHARACTER (U+FFFD) に置き換えられます" とのことです。U+FFFD は UTF-8 のバイト列では EF BF BD となります。

ということは、Shift_JIS の日本語の文字列は(多分、他の非 ASCII 文字も)、ASP.NET Core ではその文字列を処理する際デコードできず、REPLACEMENT_CHARACTER に置き換えられ、その UTF-8 のバイト列 EF BF BD がサーバーから送られてきたということのようです。

何故 Core ベースのアプリでは View の文字コードが Shift_JIS になってしまうのか、何故 Shift_JIS ではデコードできないのかは不明ですが、解決するには View の文字コードを UTF-8 にするだけで OK です。

ただし、Visual Studio のオプション設定などで自動的に UTF-8 で保存する方が見つかりません。なので、プリミティブな方法ですが、メモ帳で当該 View を開いて UTF-8 で保存し直すことでとりあえず解決しました。

最後に、上の画���を表示した View をどのように作ったかを書いておきます。

まず、以下のような Controller と Model を作ります。(Controller と Model が一緒になっているのは単に分けるのが面倒だったからです)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace AspNetCore.Controllers
{
  public class SampleModel
  {
    public string FirstName { set; get; }
    public string LastName { set; get; }
  }

  public class HomeController : Controller
  {
    public IActionResult Sample()
    {
      ViewData["SubTitle"] = "日本語";

      var model = new List<SampleModel>
      {
        new SampleModel() {FirstName="山田",LastName="太郎"},
        new SampleModel() {FirstName="日本",LastName="花子"}
      };

      return View(model);
    }
  }
}

上のコードにある SampleModel をベースにスキャフォールディング機能を利用して View を自動生成します。具体的には、以下の画像のように、Visual Studio のソリューションエクスプローラで、View のフォルダを右クリック ⇒[追加(D)]⇒[ビュー(V)...]で「ビューの追加」ダイアログを開き、必要な情報を入力して[追加]ボタンをクリックします。

「ビューの追加」ダイアログ

生成される View のコードは以下のようになります。文字コードは Shift_JIS になりますが、この時点では日本語が含まれていませんので問題は出ないです。

@model IEnumerable<AspNetCore.Controllers.SampleModel>

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

<h2>Sample</h2>

<p>
  <a asp-action="Create">Create New</a>
</p>
<table class="table">
  <thead>
    <tr>
      <th>
        @Html.DisplayNameFor(model => model.FirstName)
      </th>
      <th>
         @Html.DisplayNameFor(model => model.LastName)
      </th>
      <th></th>
    </tr>
  </thead>
  <tbody>
@foreach (var item in Model) {
    <tr>
      <td>
        @Html.DisplayFor(modelItem => item.FirstName)
      </td>
      <td>
        @Html.DisplayFor(modelItem => item.LastName)
      </td>
            
      ・・・中略・・・

    </tr>
}
  </tbody>
</table>

Visual Studio のエディタから上のコードの一部を、以下のように日本語にします。

@model IEnumerable<AspNetCore.Controllers.SampleModel>

@{
    ViewData["Title"] = "日本語";
}

<h2>@ViewData["SubTitle"]</h2>

<p>日本語</p>

<p>
  <a asp-action="Create">Create New</a>
</p>

・・・以下略・・・

これを Visual Studio のバイナリエディタで開いたのが以下の画像です。"日本語" の文字列が 93 FA 96 7B 8C EA と Shift_JIS のバイト列になっているのが分かるでしょうか。

バイナリエディタで表示

この状態の View を表示させたのが一番上の画像です。

文字化けしているのは ViewData["Title"] = "日本語"; として _Layout.cshtml に渡し、それから title タグに設定した文字列(一番上の画像で上の赤枠)と、<p>日本語</p> とした部分(下の赤枠)です。

Controller で ViewData["SubTitle"] = "日本語"; としたり、Model から DisplayFor 経由で View に渡した日本語の文字列は問題ありません。

一般的にまだ枯れてないフレームワークにはいろいろ不具合があると思いますが、今回の問題もそういった不具合の一つということでしょうか。

ちなみに、ビューのフォルダを右クリック⇒[追加(D)]をクリック ⇒[新しい項目(W)...]をクリック ⇒[MVC ビューページ]を選択して名前を付けて[追加(A)]をクリック・・・で生成される空の View ファイルは UTF-8 になります。なので、やはり本来は UTF-8 になるべきなのであろうと思います。

ググって調べてもこの問題は日本語の記事には見つからなかったのですが、英語の stackoverflow には同様な問題の報告がありました。

Special characters in Razor template not being encoded correctly

Asp net core MVC View creating view default encoding VS 2017

前者の記事のコメントに known issue だとして Encoding in scaffolded Items へのリンクが張ってあって、その記事によると "closed this on May 6 2016" となっていますが、直ってません。どういうことかは不明です。

Tags: , ,

CORE

About this blog

2010年5月にこのブログを立ち上げました。主に ASP.NET Web アプリ関係の記事です。

Calendar

<<  2024年4月  >>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

View posts in large calendar