なか日記

一度きりの人生、楽しく生きよう。

ASP.NET Identity:ユーザ情報に独自の項目を追加する

ASP.NET Identityを使うと簡単にユーザー認証の仕組みが追加できます。

でも、標準では下の画面のように電子メール(アカウントIDになる)とパスワードしかありません。「必要な項目があれば自分でカスタマイズしてね」って事ですね。

f:id:nakaji999:20141010002614p:plain

そんなわけで、カスタマイズする方法をちょこっと書いておこうと思います。

といっても、EntityFrameworkを知ってたら大した話ではないんですけどね。

このエントリでは氏名を登録する項目を追加してみることにします。

マイグレーションを有効にする

※この作業はプロジェクトを作成直後のようにデータベースが作成されていない状態では不要です。

パッケージマネージャコンソールから以下のコマンドを実行します。

PM> Enable-Migrations

Modelの変更

プロパティを追加する

ApplicationUser クラスに Name プロパティを追加します。

    public class ApplicationUser : IdentityUser
    {
        public string Name { get; set; }

データベースをマイグレーションする

※この作業はプロジェクトを作成直後のようにデータベースが作成されていない状態では不要です。

パッケージマネージャコンソールから以下のコマンドを実行します。

PM> Add-Migration AddNamePropertyToApplicationUser
PM> Update-Database

これで AspNetUsers テーブルに Name という項目が追加されました。

ViewModelの変更

View とやりとりするための ViewModel を変更します。

ユーザー登録の画面に項目を追加したいので、RegisterViewModel クラスに Name プロパティを追加します。

    public class RegisterViewModel
    {
        [Required]
        [Display(Name = "氏名")]
        public string Name { get; set; }

        [Required]
        [EmailAddress]
        [Display(Name = "電子メール")]
        public string Email { get; set; }
    // ~以下略~

Viewの変更

Register.cshtml に RegisterViewModel に追加した Name プロパティと連携するためのコードを追加します。

@using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
    @Html.AntiForgeryToken()
    <h4>新しいアカウントを作成します。</h4>
    <hr />
    @Html.ValidationSummary("", new { @class = "text-danger" })
    <div class="form-group">
        @Html.LabelFor(m => m.Name, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Name, new { @class = "form-control" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
        <div class="col-md-10">
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
        </div>
    </div>
    // ~以下略~

Controllerの変更

ViewからPOSTされたデータを元に、ユーザーを作成している AccountController クラスの Register メソッドを修正します。ApplicationUser クラスの Name プロパティに RegisterViewModel の Name プロパティをセットしましょう。

    // POST: /Account/Register
    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Register(RegisterViewModel model)
    {
        if (ModelState.IsValid)
        {
            var user = new ApplicationUser { UserName = model.Email, Email = model.Email, Name = model.Name };
            var result = await UserManager.CreateAsync(user, model.Password);
    // ~以下略~

おしまい

これでユーザー登録時に氏名を登録できるようになりました。

f:id:nakaji999:20141010014415p:plain

Twitter等の外部認証を行っている場合には、下記処理にも同様な処置を行っておきましょう。

  • ExternalLoginConfirmationViewModel クラスに Name プロパティ追加
  • ExternalLoginConfirmation.cshtml に入力項目追加
  • AccountController クラスの ExternalLoginConfirmation メソッドで ApplicationUser クラスの Name プロパティセット

おまけ

今回は手動でマイグレーションしましたけど、面倒くさいとか、開発途中でモデルがコロコロ変わる場合には自動マイグレーションの設定をしておけばいいと思います。

以下のような感じでいいと思います。

マイグレーションを有効にしてない場合

最初にパッケージマネージャコンソールで以下のように「-Auto」オプションを付けます。

PM> Enable-Migrations -Auto

マイグレーションを有効にしてしまってる場合

Configuration クラスのコンストラクタで、AutomaticMigrationsEnabled を true にします。

    internal sealed class Configuration : DbMigrationsConfiguration<WebApplication9.Models.ApplicationDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
    // ~以下略~

データベースのイニシャライザを指定する

Startup クラスでイニシャライザを指定します。

    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext,Configuration>());
            ConfigureAuth(app);
        }
    }