lycheejam's tech log

チラ裏のメモ帳 | プログラミングは苦手、インフラが得意なつもり。

ASP.NET Core MVC スキャフォールドでコードを自動生成する

概要

ASP.NET Core MVC で認証付きプロジェクトを作成した際に ASP.NET Core Identity の認証関連をカスタマイズしたいことが多々あります。
ASP.NET Core MVC のテンプレートでは ASP.NET Core Identity のコードが生成されておらずカスタマイズできません。
そこでスキャフォールディングを行い認証関連(ログインやユーザ登録)のコードを生成しカスタマイズします。

Windows 環境の VisualStudio 2017 でスキャフォールディングする方法は多く紹介されていますが Mac 環境で dotnet CLI を使用した方法はあまり紹介されていません。
自身の備忘録としてブログに残しておきます。

この記事ではスキャフォールディング( Scaffold )の方法のみ記載しカスタマイズについては触れません。

目次

参考サイト様

環境

  • Mac OS X Mojave 10.14.3
  • VisualStudio Community 2017 for Mac 7.8.3
    or
    VisualStudio Code 1.32.2
$ dotnet --version
2.2.104

dotnet CLI でスキャフォールディング

事前準備(サンプルプロジェクトの作成)

今回は ASP.NET Core MVCテンプレートの認証付きプロジェクトを作成します。

$ dotnet new mvc -n scaffold-sample -au Individual
テンプレート "ASP.NET Core Web App (Model-View-Controller)" が正常に作成されました。
このテンプレートには Microsoft 以外からのテクノロジが含まれています。詳細については https://aka.ms/aspnetcore-template-3pn-210 をご覧ください。

必要があればソリューションファイルにプロジェクトを追加します。

$ dotnet sln blog-sample.sln add scaffold-sample/scaffold-sample.csproj
プロジェクト `scaffold-sample/scaffold-sample.csproj` をソリューションに追加しました。

不要部分は省略しましたが Areas 配下に Identity ディレクトリが作成されていることが確認できます。
しかし、Login 画面などは作成されていない状況です。

$ tree scaffold-sample/
scaffold-sample/
├── Areas
│   └── Identity
│       └── Pages
│           └── _ViewStart.cshtml
├── Controllers
# 省略
25 directories, 63 files

事前準備(ツール&参照の追加)

ASP.NET Core Identity 関連のコードを生成するために必要なツールのインストールとプロジェクト参照の追加を行います。。

手順については下記の公式ドキュメントの通りです。

Codegenerator のインストール

dotnet tool の Codegenerator をインストールします。
インストール済みであればこの作業は不要です。

# インストール
$ dotnet tool install -g dotnet-aspnet-codegenerator
# インストール確認
$ dotnet tool list -g
パッケージ ID                         バージョン       コマンド
------------------------------------------------------------------------
dotnet-aspnet-codegenerator      2.2.2       dotnet-aspnet-codegenerator

プロジェクト参照の追加

Codegenerator を使用するために必要なライブラリを追加します。
このライブラリを追加せずにスキャフォールディングを実行した場合はエラーが発生し参照を追加しなさいと怒られます。

# 怒られた例
$ dotnet aspnet-codegenerator identity -h
# 省略
Selected Code Generator: identity
No code generator found with the name 'identity'.

No code generators are available in this project. Please add the 'Microsoft.VisualStudio.Web.CodeGeneration.Design' NuGet package to the project.Please add Microsoft.VisualStudio.Web.CodeGeneration.Design package to the project as a NuGet package reference.

RunTime 00:00:02.84

下記の通り参照を追加します。
この部分は VisualStudio から NuGet パッケージを追加可能です。
今回は CLI を使用して参照を追加します。

# 参照追加
$ dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design
log  : /Users/<USER>/<WORK DIR>/blog-sample/scaffold-sample/scaffold-sample.csproj の復元が 16.85 sec で完了しました。
# 参照確認
$ dotnet list scaffold-sample.csproj package
プロジェクト 'scaffold-sample' に次のパッケージ参照が含まれています
   [netcoreapp2.2]:
   最上位レベル パッケージ                                               要求済み        解決済み
   > Microsoft.AspNetCore.App                           (A)   [2.2.0, )   2.2.0
   > Microsoft.AspNetCore.Razor.Design                        2.2.0       2.2.0
   > Microsoft.EntityFrameworkCore.Sqlite                     2.2.2       2.2.2
   > Microsoft.NETCore.App                              (A)   [2.2.0, )   2.2.0
   > Microsoft.VisualStudio.Web.CodeGeneration.Design         2.2.3       2.2.3

スキャフォールディングの実行

スキャフォールディングを実行してコードを生成します。 Windows 環境の VS 2017であれば右クリックでスキャフォールディングする方法がよく紹介されています。
Mac の場合は dotnet CLI を使用してコードを生成します。

コマンドオプションの確認

下記のコマンドで Arguments のリストが確認可能です。
今回は認証関連のページを生成したいので Identity を選択します。

# Argumentsの指定なしでヘルプを確認 Arguments リストが確認できる。
$ dotnet aspnet-codegenerator -h
Usage: aspnet-codegenerator [arguments] [options]

Arguments:
  generator  Name of the generator. Check available generators below.
# 省略
Available generators:
  view      : Generates a view.
  area      : Generates an MVC Area.
  controller: Generates a controller.
  identity  : Generates an MVC Area with controllers and
  razorpage : Generates RazorPage(s).

Arguments を指定しヘルプを参照すると Arguments 毎のオプションが確認可能です。

# Argumentsを指定してヘルプを確認 Argument に対するオプションが確認できる。
$ dotnet aspnet-codegenerator identity -h
# 省略
Selected Code Generator: identity

Generator Options:
  --dbContext|-dc       : Name of the DbContext to use, or generate (if it does not exist).
  --files|-fi           : List of semicolon separated files to scaffold. Use the --list-files option to see the available options.
  --listFiles|-lf       : Lists the files that can be scaffolded by using the '--files' option.
  --userClass|-u        : Name of the User class to generate.
  --useSqLite|-sqlite   : Flag to specify if DbContext should use SQLite instead of SQL Server.
  --force|-f            : Use this option to overwrite existing files.
  --useDefaultUI|-udui  : Use this option to setup identity and to use Default UI.
  --layout|-l           : Specify a custom layout file to use.
  --generateLayout|-gl  : Use this option to generate a new _Layout.cshtml
  --bootstrapVersion|-b : Specify the bootstrap version. Valid values: '3', '4'. Default is 4.

生成可能ページの確認

上記のオプション一覧で確認できた --listFiles オプションを付けることで生成可能なファイル(コード)一覧が確認できます。
実際にコマンドを発行するとわかりますがユーザ認証・管理関連のページ一覧が出力されます。

$ dotnet aspnet-codegenerator identity -lf
Building project ...
Finding the generator 'identity'...
Running the generator 'identity'...
File List:
Account.AccessDenied
Account.ConfirmEmail
Account.ExternalLogin
# 以下省略

スキャフォールディングする際のDbContextについて

スキャフォールディングでコードを生成する際は DbContext を指定する。
既存の DbContext を指定しなかった場合は Codegenerator が自動的に DbContext を作成する。

公式ドキュメントによると DbContext の指定には完全装飾名を指定するようにとある。

// 英語版
Use the correct fully qualified name for your DB context:
// 日本語版(機械翻訳
DB コンテキストの正しい完全修飾名を使用します。
ASP.NET Core プロジェクトでスキャフォールディング Id | Microsoft Docs

DbContext の指定方法はディレクトリパスを指定するのではなくnamespace + DbContext名を指定すればいい。

生成コードを指定して生成(1つ)

$ dotnet aspnet-codegenerator identity -dc scaffold_sample.Data.ApplicationDbContext -fi Account.Login
Building project ...
Finding the generator 'identity'...
Running the generator 'identity'...
RunTime 00:00:16.15

プロジェクトディレクトリの Areas/Identity/Pages/Account 配下に生成されました。
生成された成果物についてはこちらのコミット履歴を確認ください。

生成コードを指定して生成(複数)

先程と要領は変わらないが --files オプションで指定するコード群を "(ダブルクオート) で囲む必要がある。
また、区切り文字は ;(セミコロン) となる。

$ dotnet aspnet-codegenerator identity -dc scaffold_sample.Data.ApplicationDbContext -fi "Account.ExternalLogin;Account.Manage.Index;Account.Manage.PersonalData"
Building project ...
Finding the generator 'identity'...
Running the generator 'identity'...
RunTime 00:00:14.52

今回は下記の3つを指定した。

  • Account.ExternalLogin
  • Account.Manage.Index
  • Account.Manage.PersonalData

それぞれ、外部認証ログイン画面・アカウント管理画面(TOP)・アカウント管理画面(個人情報)の機能となる。

生成された成果物は以下の通り。
アカウント管理画面( Manage )を生成した際の初期コードも一緒にコミットされている。

コードを指定無しで全生成

生成可能なコードを全て生成する場合は --files オプションを指定せずにコマンドを発行します。
また、上述の手順に従って既存の Codegenerator によって生成されたファイルがある場合はエラーとなってしまうので --force オプションを指定して強制的に上書きします。
既にコードをカスタマイズしている場合は消えてしまうので注意。

$ dotnet aspnet-codegenerator identity -dc scaffold_sample.Data.ApplicationDbContext -f
Building project ...
Finding the generator 'identity'...
Running the generator 'identity'...
RunTime 00:00:12.06

生成された成果物は以下の通り。

以上、他のコード生成のパターンでも手順はほぼ同じと思われる。(試してない。)

雑感

この方法がわからなくてGitHub経由でWindows PCに同期してVisualStudioでスキャフォールディングした思い出...