情報応用演習Ⅰ(2024)

【T9a】簡易ブログソフトウェアの作成 Part.Ⅰ ~ 認証機能の組み込み(5/14)

プロジェクトタイプASP.NET Core Web アプリ(Model-View-Controller)
プロジェクト名T9a
ソリューション名PIT9
ターゲットフレームワーク.NET 8.0(長期的なサポート)
最上位レベルのステートメントを使用しない使用する(チェックオフ)
注意
  • 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
    • 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
    • プロジェクトの作成作業については準備作業を参照せよ.

9a-5. データモデルの検討と定義

最初にデータモデルとデータコンテキストクラスを定義しよう.

「ユーザー」に相当するモデルクラスは前節で説明した通り,IdentityUserクラスから派生したクラスとして定義する必要がある. このエンティティには表9a-3-1のデータ項目に加えて_に示すデータ項目を追加することにする.

「ユーザー」に追加するデータ項目
項目名必須/任意データ型備考
ニックネーム任意文字列設定した場合はユーザー名の代わりにニックネームを表示する.
登録日時必須日付時刻このユーザーをシステムに登録した日時.

クラス名はBlogUserとする.プロジェクト内の Models フォルダを右クリックし,「追加」→「クラス」をクリックする. 作成するクラス名を訊かれるのでBlogUser(.csは省略可能)と入力して「追加」ボタンをクリックする. すると空のクラス定義が作られるので_の定義を書き込もう.

「ユーザー」クラス
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using Microsoft.AspNetCore.Identity;         // 追記
using System.ComponentModel.DataAnnotations; // 追記

namespace T9a.Models
{
    // 「ユーザー」クラス
    public class BlogUser : IdentityUser
    {
        [Display(Name = "ユーザー名")]
        public override string UserName { get => base.UserName; set => base.UserName = value; }

        [Display(Name = "メールアドレス")]
        [EmailAddress]
        public override string Email { get => base.Email; set => base.Email = value; }

        [Display(Name = "ニックネーム")]
        public string? Nickname { get; set; }

        [Display(Name = "登録日時")]
        [DataType(DataType.DateTime)]
        public DateTime Registered { get; set; }
    }
}

前述した通りこのBlogUserクラスは,IdentityUserクラスから派生させている.

UserNameプロパティとEmailプロパティに関しては, override キーワードを打ち込めばその実装は自動的に補完してくれる. これらのプロパティはIdentityUserクラスで定義されている仮想プロパティであり,ここでは基底クラスの get / set にただ転送しているだけであるため一見オーバーライドする意味はないように見えるが, 今回は[Display]属性や[EmailAddress]属性といった属性を設定する必要があるためあえてこのような方法をとっている.

_で示した2つのデータ項目に相当するのが,NicknameプロパティとRegisteredプロパティである.

つぎにデータコンテキストクラスを定義する.プロジェクト内に Data というフォルダを作成し, これを右クリックして「追加」→「クラス」をクリックする.作成するクラス名を訊かれるので T9aContext(.csは省略可能)と入力して「追加」ボタンをクリックする. すると空のクラス定義が作られるので_のように書き換えよう.

T9aContextクラスの定義
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; // 追記
using Microsoft.EntityFrameworkCore;                     // 追記
using T9a.Models;                                        // 追記

namespace T9a.Data
{
    public class T9aContext : IdentityDbContext<BlogUser>
    {
        public T9aContext(DbContextOptions<T9aContext> contextOptions)
            : base(contextOptions)
        { }
    }
}

これも前節で解説した通り,ASP.NET Identity の枠組みを利用するためには,通常のデータコンテキストクラスとは異なり IdentityDbContext<TUser>ジェネリッククラスから派生させる必要がある. ASP.NET Core Identity のユーザークラスを拡張して使用する場合は,_のようにジェネリックパラメータ TUserにそのアプリの「ユーザー」として使用するモデルクラスを指定する.つまり,そのアプリで使用する「ユーザー」クラスを IdentityUserクラスの派生クラスと表現するならば,そのアプリのデータコンテキストクラスは IdentityDbContext<IdentityUserクラスの派生クラス>から派生させればよい,ということである.

次に Program.cs と appsettings.json にそれぞれ__に示す内容を追記しよう.

Program.csの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using KnzwTech.AspNetCore.ResourceBasedLocalization;
using Microsoft.EntityFrameworkCore; // 追記
using T9a.Data;                      // 追記

AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews(opt => opt.EnableDefaultErrorMessagesFromResource());

builder.Services.AddDbContext<T9aContext>(
    opt => opt.UseNpgsql(builder.Configuration.GetConnectionString(nameof(T9aContext))));

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();

app.UseStatusCodePagesWithReExecute("/Home/AccessError/{0}");

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();
appsettings.jsonの追記内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*", // ←ここカンマを追記するの忘れないように!
  "ConnectionStrings": {
    "T9aContext": "Host=localhost;Port=5432;Username=t9a_user;Database=t9a_db;Password=Xbi!YzNm5"
  }
}

ここまで追記したらpgAdminで_に合わせて接続ユーザーを作成して,Visual Studio でコマンドラインターミナル1dotnet ef migrations add / dotnet ef database update コマンドを実行して データベースを構築しよう(__).なお今回は前回と異なりアプリケーション内で使用するデータコンテキストクラスは _で定義したT9aContextクラスただ一つなので-cオプションを指定する必要はない. データベースへのマイグレーションを済ませると,_に示す通りのテーブルが作られているはずである.

一見,_で定義したBlogUserに相当するテーブルが作られていないように見えるかもしれないが, 今回はBlogUserクラスに対応するテーブルはAspNetUsersテーブルとなる.これはデータコンテキストクラスをIdentityDbContext<BlogUser>から 派生させたためである.ASP.NET Core Identity では「ユーザー」に対応するテーブルはデフォルトではAspNetUsersという名前をもつようになっている. 実際AspNetUsersテーブルの定義を見ると,表9a-3-1に示す列に加えて, Nickname列とRegistered列が追加されていることが分かるだろう(_).

データベースの構築

  1. タブのタイトルは「開発用PowerShell」もしくは「Developer PowerShell」となっている. ↩︎

Last updated on 2024-06-19
Published on 2024-06-19

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.