Alıştırma - Identity’yi Özelleştirme

Tamamlandı

Identity, kullanıcıyı varsayılan olarak IdentityUser sınıfıyla temsil eder. Kayıt sırasında yakalanan verileri genişletmenin yollarından biri, IdentityUser sınıfından türetilen bir sınıf oluşturmaktır. Bu ünitede, ContosoPetsUser adlı bir türetilmiş sınıf oluşturulur. ContosoPetsUser, kullanıcının adını ve soyadını depolamaya yönelik özellikleri içerir.

derived IdentityUser sınıfı.

Ek kullanıcı profili bilgilerini toplamak için kullanıcı arabiriminde değişiklik yapılması da gerekir. Aşağıdaki adımlar, kayıtlı kullanıcının ad ve soyadı bilgilerini toplama işlemini açıklar.

Kullanıcı hesabı verilerini özelleştirme

  1. Değiştirilecek kullanıcı kaydı dosyalarını projeye ekleyin:

    dotnet aspnet-codegenerator identity \
        --dbContext ContosoPetsAuth \
        --files "Account.Manage.EnableAuthenticator;Account.Manage.Index;Account.Register" \
        --userClass ContosoPetsUser \
        --force
    

    Yukarıdaki komutta:

    • --dbContext seçeneği DbContext sınıfından türetilmiş ContosoPetsAuth sınıfına yönelik bilgileri araca sağlar.
    • --files seçeneği Identity alanına eklenecek benzersiz dosyaların noktalı virgülle ayrılmış listesini belirtir.
    • --userClass seçeneği, IdentityUser sınıfından türetilmiş ContosoPetsUser sınıfının oluşturulmasıyla sonuçlanır.
    • --force seçeneği Identity alanında bulunan mevcut dosyaların üzerine yazılmasına neden olur.

    İpucu

    --files seçeneğine yönelik geçerli değerleri görüntülemek için proje kökünde aşağıdaki komutu çalıştırın:

    dotnet aspnet-codegenerator identity --listFiles
    

    Aşağıdaki dosyalar Areas/Identity dizinine eklenir:

    • Data/
      • ContosoPetsUser.cs
    • Pages/
      • _ViewImports.cshtml
      • Account/
        • _ViewImports.cshtml
        • Register.cshtml
        • Register.cshtml.cs
        • Manage/
          • _ManageNav.cshtml
          • _ViewImports.cshtml
          • EnableAuthenticator.cshtml
          • EnableAuthenticator.cshtml.cs
          • Index.cshtml
          • Index.cshtml.cs
          • ManageNavPages.cs

    Buna ek olarak, --force seçeneği kullanıldığından yukarıdaki komut çalıştırılmadan önce mevcut olan Data/ContosoPetsAuth.cs dosyasının da üzerine yazılır. ContosoPetsAuth sınıf bildirimi şimdi yeni oluşturulan ContosoPetsUser kullanıcı türüne başvurur:

    public class ContosoPetsAuth : IdentityDbContext<ContosoPetsUser>
    

    EnableAuthenticator Razor sayfası iskeleli hale getirildi. Ancak, bu sayfa modülün sonraki kısımlarına kadar değiştirilmeyecek.

  2. Areas/Identity/IdentityHostingStartup.cs dosyasının Configure metodunda AddDefaultIdentity çağrısının yeni Identity kullanıcı türüyle ilgili bilgi sahibi olması gerekir. Aşağıda vurgulanan değişikliği ekleyip dosyayı kaydedin.

    services.AddDefaultIdentity<ContosoPetsUser>()
        .AddDefaultUI()
        .AddEntityFrameworkStores<ContosoPetsAuth>();
    
  3. Aşağıda vurgulanan değişiklikleri eklemek için Pages/Shared/_LoginPartial.cshtml dosyasını güncelleştirin. Yaptığınız değişiklikleri kaydedin.

    @using Microsoft.AspNetCore.Identity
    @using ContosoPets.Ui.Areas.Identity.Data
    @inject SignInManager<ContosoPetsUser> SignInManager
    @inject UserManager<ContosoPetsUser> UserManager
    
    <ul class="navbar-nav">
    

    Yukarıdaki değişiklikler, @inject yönergelerinde SignInManager<T> ve UserManager<T> öğelerine geçirilen kullanıcı türünü güncelleştirir. Varsayılan IdentityUser türünün yerine artık ContosoPetsUser kullanıcısına başvurulur. ContosoPetsUser başvurularını çözümlemek için @using yönergesi eklendi.

    Pages/Shared/_LoginPartial.cshtml, fiziksel olarak Identity alanının dışında bulunur. Sonuç olarak, dosya iskele aracı tarafından otomatik olarak güncelleştirilmedi. Uygun değişikliklerin el ile yapılması gerekti.

    İpucu

    _LoginPartial.cshtml dosyasını el ile düzenlemeye alternatif olarak dosya, iskele aracı çalıştırılmadan önce silinebilir. _LoginPartial.cshtml dosyası, yeni ContosoPetsUser sınıfına yönelik başvurular ile yeniden oluşturulur.

  4. Ek kullanıcı profili verilerinin alınmasını ve depolanmasını desteklemek için Areas/Identity/Data/ContosoPetsUser.cs dosyasını güncelleştirin. Aşağıdaki değişiklikleri yapın:

    1. FirstName ve LastName özelliklerini ekleyin:

      public class ContosoPetsUser : IdentityUser
      {
          [Required]
          [MaxLength(100)]
          public string FirstName { get; set; }
      
          [Required]
          [MaxLength(100)]
          public string LastName { get; set; }
      }
      

      Yukarıdaki kod parçacığındaki özellikler, temel alınan AspNetUsers tablosunda oluşturulacak ek sütunları temsil eder. Her iki özellik de gerekli olduğundan, bunlara [Required] özniteliğiyle not eklenir. [Required] özniteliği aynı zamanda, temel alınan veritabanı tablosu sütununda null olmama kısıtlamasıyla sonuçlanır. Ayrıca, [MaxLength] özniteliği maksimum uzunluk olarak 100 karaktere izin verildiğini belirtir. Temel alınan tablo sütununun veri türü de buna uygun olarak tanımlanır.

    2. Aşağıdaki using deyimini dosyanın en üstüne ekleyin. Yaptığınız değişiklikleri kaydedin.

      using System.ComponentModel.DataAnnotations;
      

      Yukarıdaki kod, FirstName ve LastName özelliklerine uygulanan veri açıklaması özniteliklerini çözümler.

Veritabanını güncelleştirme

  1. Temel alınan veri deposunu güncelleştirmek için EF Core geçişi oluşturma ve uygulama:

    dotnet ef migrations add UpdateUser && \
        dotnet ef database update
    

    UpdateUser EF Core geçişi, AspNetUsers tablosunun şemasına bir DDL değişiklik betiği uyguladı. Aşağıdaki geçiş çıkışı alıntısında görüldüğü gibi, özellikle FirstName ve LastName sütunları eklendi:

    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (1,005ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      ALTER TABLE "AspNetUsers" ADD "FirstName" character varying(100) NOT NULL DEFAULT '';
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
        Executed DbCommand (517ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
        ALTER TABLE "AspNetUsers" ADD "LastName" character varying(100) NOT NULL DEFAULT '';
    
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
        Executed DbCommand (37ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
        ALTER TABLE [AspNetUsers] ADD [FirstName] nvarchar(100) NOT NULL DEFAULT N'';
    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
        Executed DbCommand (36ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
        ALTER TABLE [AspNetUsers] ADD [LastName] nvarchar(100) NOT NULL DEFAULT N'';
    

    UpdateUser EF Core geçişi tarafından AspNetUsers tablosunun şemasına uygulanan etkileri analiz etmek için aşağıdaki adımları izleyin. Identity veri modelini genişletmenin, temel alınan veri deposu üzerindeki etkilerine yönelik bilgi edinirsiniz.

  1. Tablo şemasını görüntülemek için aşağıdaki komutu çalıştırın:

    db -c '\d "AspNetUsers"'
    

    Aşağıdaki çıkış görüntülenir:

                                        Table "public.AspNetUsers"
            Column        |           Type           | Collation | Nullable |        Default
    ----------------------+--------------------------+-----------+----------+-----------------------
     Id                   | text                     |           | not null |
     UserName             | character varying(256)   |           |          |
     NormalizedUserName   | character varying(256)   |           |          |
     Email                | character varying(256)   |           |          |
     NormalizedEmail      | character varying(256)   |           |          |
     EmailConfirmed       | boolean                  |           | not null |
     PasswordHash         | text                     |           |          |
     SecurityStamp        | text                     |           |          |
     ConcurrencyStamp     | text                     |           |          |
     PhoneNumber          | text                     |           |          |
     PhoneNumberConfirmed | boolean                  |           | not null |
     TwoFactorEnabled     | boolean                  |           | not null |
     LockoutEnd           | timestamp with time zone |           |          |
     LockoutEnabled       | boolean                  |           | not null |
     AccessFailedCount    | integer                  |           | not null |
     FirstName            | character varying(100)   |           | not null | ''::character varying
     LastName             | character varying(100)   |           | not null | ''::character varying
    

    ContosoPetsUser sınıfındaki FirstName ve LastName özellikleri, yukarıdaki çıkışta bulunan FirstName ve LastName sütunlarına karşılık gelir. [MaxLength(100)] öznitelikleri nedeniyle her iki sütuna da character varying(100) veri türü atandı. [Required] öznitelikleri nedeniyle null olmama kısıtlaması eklendi.

  2. Komut kabuğunda, aşağıdaki dizin bilgileri görüntülenene kadar aşağı kaydırın:

    Indexes:
        "PK_AspNetUsers" PRIMARY KEY, btree ("Id")
        "UserNameIndex" UNIQUE, btree ("NormalizedUserName")
        "EmailIndex" btree ("NormalizedEmail")
    

    PK_AspNetUsers dizini, Id sütununun bir kullanıcı hesabına yönelik benzersiz tanıtıcı olduğunu gösterir.

  3. Komut kabuğundaki metin görüntüleyicisinden çıkmak için q tuşuna basın.

  1. Tablo şemasını görüntülemek için aşağıdaki komutu çalıştırın:

    db -Q "SELECT COLUMN_NAME, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH AS MAX_LENGTH FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='AspNetUsers'" -Y 20
    

    Aşağıdaki çıkış görüntülenir:

    COLUMN_NAME          IS_NULLABLE DATA_TYPE            MAX_LENGTH
    -------------------- ----------- -------------------- -----------
    Id                   NO          nvarchar                     450
    UserName             YES         nvarchar                     256
    NormalizedUserName   YES         nvarchar                     256
    Email                YES         nvarchar                     256
    NormalizedEmail      YES         nvarchar                     256
    EmailConfirmed       NO          bit                         NULL
    PasswordHash         YES         nvarchar                      -1
    SecurityStamp        YES         nvarchar                      -1
    ConcurrencyStamp     YES         nvarchar                      -1
    PhoneNumber          YES         nvarchar                      -1
    PhoneNumberConfirmed NO          bit                         NULL
    TwoFactorEnabled     NO          bit                         NULL
    LockoutEnd           YES         datetimeoffset              NULL
    LockoutEnabled       NO          bit                         NULL
    AccessFailedCount    NO          int                         NULL
    FirstName            NO          nvarchar                     100
    LastName             NO          nvarchar                     100
    

    ContosoPetsUser sınıfındaki FirstName ve LastName özellikleri, yukarıdaki çıkışta bulunan FirstName ve LastName sütunlarına karşılık gelir. [MaxLength(100)] öznitelikleri nedeniyle her iki sütuna da nvarchar(100) veri türü atandı. [Required] öznitelikleri nedeniyle null olmama kısıtlaması eklendi. Mevcut satırlar, yeni sütunlarda boş dizeler gösterir.

  2. Tablonun birincil anahtarını görüntülemek için aşağıdaki komutu çalıştırın:

    db -i $setupWorkingDirectory/list-aspnetusers-pk.sql -Y 15
    

    Aşağıdaki çıkış, Id sütununun bir kullanıcı hesabı için benzersiz tanıtıcı olduğunu gösterir:

    Table           Column          Primary key
    --------------- --------------- ---------------
    AspNetUsers     Id              PK_AspNetUsers
    

Kullanıcı kaydı formunu özelleştirme

  1. Areas/Identity/Pages/Account/Register.cshtml dosyasına aşağıda vurgulanmış işaretlemeyi ekleyin:

    <form asp-route-returnUrl="@Model.ReturnUrl" method="post">
        <h4>Create a new account.</h4>
        <hr />
        <div asp-validation-summary="All" class="text-danger"></div>
        <div class="form-group">
            <label asp-for="Input.FirstName"></label>
            <input asp-for="Input.FirstName" class="form-control" />
            <span asp-validation-for="Input.FirstName" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Input.LastName"></label>
            <input asp-for="Input.LastName" class="form-control" />
            <span asp-validation-for="Input.LastName" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Input.Email"></label>
            <input asp-for="Input.Email" class="form-control" />
            <span asp-validation-for="Input.Email" class="text-danger"></span>
        </div>
    

    Yukarıdaki işaretleme ile, Ad ve Soyadı metin kutuları kullanıcı kaydı formuna eklenir.

  2. Areas/Identity/Pages/Account/Register.cshtml.cs dosyasına ad metin kutuları için destek ekleyin.

    1. İç içe geçmiş InputModel sınıfına FirstName ve LastName özelliklerini ekleyin:

      public class InputModel
      {
          [Required]
          [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)]
          [Display(Name = "First name")]
          public string FirstName { get; set; }
      
          [Required]
          [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)]
          [Display(Name = "Last name")]
          public string LastName { get; set; }
      
          [Required]
          [EmailAddress]
          [Display(Name = "Email")]
          public string Email { get; set; }
      
          [Required]
          [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
          [DataType(DataType.Password)]
          [Display(Name = "Password")]
          public string Password { get; set; }
      
          [DataType(DataType.Password)]
          [Display(Name = "Confirm password")]
          [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
          public string ConfirmPassword { get; set; }
      }
      

      [Display] öznitelikleri, metin kutularıyla ilişkilendirilecek etiket metnini tanımlar.

    2. ContosoPetsUser nesnesinde FirstName ve LastName özelliklerini ayarlamak için OnPostAsync metodunu değiştirin. Aşağıda vurgulanan değişiklikleri yapın:

      public async Task<IActionResult> OnPostAsync(string returnUrl = null)
      {
          returnUrl = returnUrl ?? Url.Content("~/");
          if (ModelState.IsValid)
          {
              var user = new ContosoPetsUser
              {
                  FirstName = Input.FirstName,
                  LastName = Input.LastName,
                  UserName = Input.Email,
                  Email = Input.Email,
              };
              var result = await _userManager.CreateAsync(user, Input.Password);
              if (result.Succeeded)
              {
      

      Yukarıdaki değişiklik, FirstName ve LastName özelliklerini kayıt formundaki kullanıcı girişine ayarlar.

Site üst bilgisini özelleştirme

Kullanıcı kaydı sırasında toplanan ad ve soyadı bilgilerini görüntülemek için Pages/Shared/_LoginPartial.cshtml dosyasını güncelleştirin. Aşağıdaki kod parçacığında vurgulanan satırlar gereklidir:

@using Microsoft.AspNetCore.Identity
@using ContosoPets.Ui.Areas.Identity.Data
@inject SignInManager<ContosoPetsUser> SignInManager
@inject UserManager<ContosoPetsUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    ContosoPetsUser user = await UserManager.GetUserAsync(User);
    var fullName = $"{user.FirstName} {user.LastName}";

    <li class="nav-item">
        <a id="manage" class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" title="Manage">Hello, @fullName!</a>
    </li>
    <li class="nav-item">
        <form id="logoutForm" class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/Index", new { area = "" })">
            <button id="logout" type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" id="register" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" id="login" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Profil yönetimi formunu özelleştirme

  1. Areas/Identity/Pages/Account/Manage/Index.cshtml dosyasına aşağıda vurgulanmış işaretlemeyi ekleyin. Yaptığınız değişiklikleri kaydedin.

    <form id="profile-form" method="post">
        <div asp-validation-summary="All" class="text-danger"></div>
        <div class="form-group">
            <label asp-for="Input.FirstName"></label>
            <input asp-for="Input.FirstName" class="form-control" />
            <span asp-validation-for="Input.FirstName" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Input.LastName"></label>
            <input asp-for="Input.LastName" class="form-control" />
            <span asp-validation-for="Input.LastName" class="text-danger"></span>
        </div>
        <div class="form-group">
            <label asp-for="Username"></label>
            <input asp-for="Username" class="form-control" disabled />
        </div>
    
  2. Ad metin kutularına yönelik desteği sunmak için Areas/Identity/Pages/Account/Manage/Index.cshtml.cs dosyasında aşağıdaki değişiklikleri yapın.

    1. İç içe geçmiş InputModel sınıfına FirstName ve LastName özelliklerini ekleyin:

      public class InputModel
      {
          [Required]
          [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)]
          [Display(Name = "First name")]
          public string FirstName { get; set; }
      
          [Required]
          [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 1)]
          [Display(Name = "Last name")]
          public string LastName { get; set; }
      
          [Phone]
          [Display(Name = "Phone number")]
          public string PhoneNumber { get; set; }
      }
      
    2. LoadAsync metodunda vurgulanan değişiklikleri ekleyin:

      private async Task LoadAsync(ContosoPetsUser user)
      {
          var userName = await _userManager.GetUserNameAsync(user);
          var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
      
          Username = userName;
      
          Input = new InputModel
          {
              PhoneNumber = phoneNumber,
              FirstName = user.FirstName,
              LastName = user.LastName,
          };
      }
      

      Yukarıdaki kod, profil yönetimi formunun karşılık gelen metin kutularında görüntülenmesi için ad ve soyadı bilgilerinin alınmasına yönelik destek sunar.

    3. Vurgulanan değişiklikleri OnPostAsync metoduna ekleyin. Yaptığınız değişiklikleri kaydedin.

      public async Task<IActionResult> OnPostAsync()
      {
          var user = await _userManager.GetUserAsync(User);
          if (user == null)
          {
              return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
          }
      
          if (!ModelState.IsValid)
          {
              await LoadAsync(user);
              return Page();
          }
      
          user.FirstName = Input.FirstName;
          user.LastName = Input.LastName;
          await _userManager.UpdateAsync(user);
      
          var phoneNumber = await _userManager.GetPhoneNumberAsync(user);
          if (Input.PhoneNumber != phoneNumber)
          {
              var setPhoneResult = await _userManager.SetPhoneNumberAsync(user, Input.PhoneNumber);
              if (!setPhoneResult.Succeeded)
              {
                  var userId = await _userManager.GetUserIdAsync(user);
                  throw new InvalidOperationException($"Unexpected error occurred setting phone number for user with ID '{userId}'.");
              }
          }
      
          await _signInManager.RefreshSignInAsync(user);
          StatusMessage = "Your profile has been updated";
          return RedirectToPage();
      }
      

      Yukarıdaki kod, veritabanının AspNetUsers tablosunda yer alan ad ve soyadı bilgilerinin güncelleştirilmesine yönelik destek sunar.

Derleme, dağıtma ve test etme

  1. Uygulamayı derlemek için aşağıdaki komutu çalıştırın:

    dotnet build --no-restore
    

    Son derlemeden sonra NuGet paketi eklenmediğinden --no-restore seçeneği de eklenmiştir. Derleme işlemi, NuGet paketlerinin geri yüklenmesini atlar ve uyarı oluşturmadan başarıyla tamamlanır. Derleme başarısız olursa, sorun giderme bilgileri için çıkışı inceleyin.

  2. Aşağıdaki komutu çalıştırarak uygulamayı Azure App Service’e dağıtın:

    az webapp up
    
  3. Tarayıcınızda uygulamaya gidin. Oturumunuz hala açıksa Oturumu kapat seçeneğini belirleyin.

    İpucu

    Uygulamanıza yönelik URL’ye ihtiyacınız varsa, aşağıdaki komut ile bunu görüntüleyin:

    echo $webAppUrl
    
  4. Yeni bir kullanıcı kaydetmek için Kaydolun’u seçip güncelleştirilmiş formu kullanın.

    Not

    Ad ve Soyadı alanlarındaki doğrulama kısıtlamaları, InputModel sınıfını FirstName ve LastName özelliklerindeki veri açıklamalarını yansıtır.

    Kaydolduktan sonra giriş sayfasına yönlendirilirsiniz. Uygulamanın üst bilgisi artık şunu içerir: Merhaba [Ad] [Soyadı]!.

  5. Ad ve soyadlarının veritabanında depolandığını doğrulamak için aşağıdaki komutu çalıştırın:

    db -c 'SELECT "UserName", "Email", "FirstName", "LastName" FROM "AspNetUsers"'
    

    Aşağıdaki çıkışın bir varyasyonu görüntülenir:

             UserName          |            Email          | FirstName | LastName
    ---------------------------+---------------------------+-----------+----------
     kai.klein@contoso.com     | kai.klein@contoso.com     |           |
     jana.heinrich@contoso.com | jana.heinrich@contoso.com | Jana      | Heinrich
    (2 rows)
    
    db -Q "SELECT UserName, Email, FirstName, LastName FROM dbo.AspNetUsers" -Y 25
    

    Aşağıdaki çıkışın bir varyasyonu görüntülenir:

    UserName                  Email                     FirstName                 LastName
    ------------------------- ------------------------- ------------------------- -------------------------
    kai.klein@contoso.com     kai.klein@contoso.com
    jana.heinrich@contoso.com jana.heinrich@contoso.com Jana                      Heinrich
    

    FirstName ve LastName öğelerini şemaya eklemeden önce kaydolan ilk kullanıcı. Sonuç olarak, ilişkili AspNetUsers tablo kaydının bu sütunlarda verileri yoktur.

Profil yönetimi formundaki değişiklikleri test etme

  1. Oluşturduğunuz ilk kullanıcıyla web uygulamasında oturum açın.

  2. Merhaba ! bağlantısına tıklayıp profil yönetimi formuna gidin.

    Not

    AspNetUsers tablosunun bu kullanıcıya yönelik satırı FirstName ve LastName değerlerini içermediğinden bağlantı düzgün şekilde görüntülenmez.

  3. Ad ve Soyadı için geçerli değerleri girin. Kaydet’i seçin.

    Uygulamanın üst bilgisi şöyle güncelleştirilir: Merhaba, [Ad] [Soyadı]!.