Oefening: identiteit aanpassen
In de vorige les hebt u geleerd hoe aanpassing werkt in ASP.NET Core Identity. In deze les breidt u het identiteitsgegevensmodel uit en voert u de bijbehorende wijzigingen in de gebruikersinterface aan.
De gebruikersinterface van het gebruikersaccount aanpassen
In deze sectie gaat u de identiteitsgebruikersinterfacebestanden maken en aanpassen die moeten worden gebruikt in plaats van de standaard Razor-klassebibliotheek.
Voeg de te wijzigen gebruikersregistratiebestanden toe aan het project:
dotnet aspnet-codegenerator identity --dbContext RazorPagesPizzaAuth --files "Account.Manage.EnableAuthenticator;Account.Manage.Index;Account.Register;Account.ConfirmEmail"
In de voorgaande opdracht:
- Met de optie
--dbContext
wordt het hulpprogramma geïnformeerd over de bestaande, vanDbContext
afgeleide klasse met de naamRazorPagesPizzaAuth
. - Met de optie
--files
geeft u een lijst met door puntkomma's gescheiden unieke bestanden op die moeten worden toegevoegd aan het gebied Identiteit.Account.Manage.Index
is de profielbeheerpagina. Deze pagina wordt verderop in deze les gewijzigd.Account.Register
is de registratiepagina van de gebruiker. Deze pagina wordt ook gewijzigd in deze eenheid.Account.Manage.EnableAuthenticator
enAccount.ConfirmEmail
zijn geveerd, maar niet gewijzigd in deze eenheid.
Tip
Voer de volgende opdracht uit vanuit de hoofdmap van het project om geldige waarden voor de
--files
optie weer te geven:dotnet aspnet-codegenerator identity --listFiles
De volgende bestanden zijn toegevoegd aan de map Areas/Identity:
- Pages/
- _ViewImports.cshtml
- Account/
- _ViewImports.cshtml
- ConfirmEmail.cshtml
- ConfirmEmail.cshtml.cs
- Register.cshtml
- Register.cshtml.cs
- Manage/
- _ManageNav.cshtml
- _ViewImports.cshtml
- EnableAuthenticator.cshtml
- EnableAuthenticator.cshtml.cs
- Index.cshtml
- Index.cshtml.cs
- ManageNavPages.cs
- Met de optie
Verlengen IdentityUser
U krijgt een nieuwe vereiste om de namen van uw gebruikers op te slaan. Omdat de standaardklasse IdentityUser
geen eigenschappen voor voor- en achternamen bevat, moet u de RazorPagesPizzaUser
klasse uitbreiden.
Breng de volgende wijzigingen aan in Areas/Identity/Data/RazorPagesPizzaUser.cs:
Voeg de eigenschappen
FirstName
enLastName
toe:using System.ComponentModel.DataAnnotations; using Microsoft.AspNetCore.Identity; namespace RazorPagesPizza.Areas.Identity.Data; public class RazorPagesPizzaUser : IdentityUser { [Required] [MaxLength(100)] public string FirstName { get; set; } = string.Empty; [Required] [MaxLength(100)] public string LastName { get; set; } = string.Empty; }
De eigenschappen in het voorgaande fragment vertegenwoordigen extra kolommen die in de onderliggende tabel
AspNetUsers
moeten worden gemaakt. Beide eigenschappen zijn vereist en hebben daarom het kenmerk[Required]
als aantekening gekregen. Daarnaast geeft het kenmerk[MaxLength]
aan dat een maximale lengte van 100 tekens is toegestaan. Het gegevenstype van de onderliggende tabelkolom is dienovereenkomstig gedefinieerd. Er wordt een standaardwaardestring.Empty
toegewezen omdat nullable context is ingeschakeld in dit project en de eigenschappen niet-nullable tekenreeksen zijn.Voeg boven in het bestand de volgende
using
-instructie toe.using System.ComponentModel.DataAnnotations;
Met de voorgaande code worden de kenmerken voor gegevensaantekeningen die zijn toegepast op de eigenschappen
FirstName
enLastName
omgezet.
De database bijwerken
Nu de modelwijzigingen zijn aangebracht, moeten de bijbehorende wijzigingen worden aangebracht in de database.
Zorg ervoor dat al uw wijzigingen worden opgeslagen.
Maak een EF Core-migratie en pas deze toe om het onderliggende gegevensarchief bij te werken:
dotnet ef migrations add UpdateUser dotnet ef database update
Voor de
UpdateUser
-EF Core-migratie is een DDL-wijzigingsscript toegepast op het schemaAspNetUsers
van de tabel. Om precies te zijn, zijn de kolommenFirstName
enLastName
toegevoegd, zoals te zien is in het volgende fragment van de migratieuitvoer: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'';
Bekijk de database om het effect van de
UpdateUser
EF Core-migratie in het schema van deAspNetUsers
tabel te analyseren.Vouw in het deelvenster SQL Server het knooppunt Kolommen in de dbo uit. De tabel AspNetUsers .
De
FirstName
enLastName
eigenschappen in deRazorPagesPizzaUser
klasse komen overeen met deFirstName
kolommenLastName
in de voorgaande afbeelding. Er is een gegevenstypenvarchar(100)
toegewezen aan elk van de twee kolommen vanwege de[MaxLength(100)]
-kenmerken. De niet-null-beperking is toegevoegd omdatFirstName
enLastName
in de klasse niet-nullable tekenreeksen zijn. Bestaande rijen bevatten lege tekenreeksen in de nieuwe kolommen.
Het gebruikersregistratieformulier aanpassen
U hebt nieuwe kolommen toegevoegd voor FirstName
en LastName
. Nu moet u de gebruikersinterface bewerken om overeenkomende velden op het registratieformulier weer te geven.
Voeg in Areas/Identity/Pages/Account/Register.cshtml de volgende gemarkeerde markeringen toe:
<form id="registerForm" asp-route-returnUrl="@Model.ReturnUrl" method="post"> <h2>Create a new account.</h2> <hr /> <div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div> <div class="form-floating mb-3"> <input asp-for="Input.FirstName" class="form-control" /> <label asp-for="Input.FirstName"></label> <span asp-validation-for="Input.FirstName" class="text-danger"></span> </div> <div class="form-floating mb-3"> <input asp-for="Input.LastName" class="form-control" /> <label asp-for="Input.LastName"></label> <span asp-validation-for="Input.LastName" class="text-danger"></span> </div> <div class="form-floating mb-3"> <input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" /> <label asp-for="Input.Email">Email</label> <span asp-validation-for="Input.Email" class="text-danger"></span> </div>
Met de voorgaande markering worden de tekstvakken Voornaam en Achternaam toegevoegd aan het gebruikersregistratieformulier.
Voeg in Areas/Identity/Pages/Account/Register.cshtml.cs ondersteuning toe voor de naamtekstvakken.
Voeg de eigenschappen
FirstName
enLastName
toe aan de geneste klasseInputModel
: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; } /// <summary> /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> [Required] [EmailAddress] [Display(Name = "Email")] public string Email { get; set; }
Met de
[Display]
-kenmerken wordt de labeltekst gedefinieerd die aan de tekstvakken moet worden gekoppeld.Wijzig de methode
OnPostAsync
om de eigenschappenFirstName
enLastName
in te stellen voor het objectRazorPagesPizza
. Voeg de volgende gemarkeerde regels toe:public async Task<IActionResult> OnPostAsync(string returnUrl = null) { returnUrl ??= Url.Content("~/"); ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList(); if (ModelState.IsValid) { var user = CreateUser(); user.FirstName = Input.FirstName; user.LastName = Input.LastName; await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None); await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None); var result = await _userManager.CreateAsync(user, Input.Password);
Met de voorgaande wijziging worden de eigenschappen
FirstName
enLastName
ingesteld voor de gebruikersinvoer van het registratieformulier.
De websiteheader aanpassen
Werk Pages/Shared/_LoginPartial.cshtml bij om de voor- en achternaam weer te geven die tijdens de gebruikersregistratie zijn verzameld. De gemarkeerde regels in het volgende codefragment zijn nodig:
<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
RazorPagesPizzaUser? 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>
UserManager.GetUserAsync(User)
retourneert een null-object RazorPagesPizzaUser
. De operator null-voorwaardelijk ?.
wordt alleen gebruikt voor toegang tot de FirstName
en LastName
eigenschappen als het RazorPagesPizzaUser
object niet null is.
Het profielbeheerformulier aanpassen
U hebt de nieuwe velden toegevoegd aan het gebruikersregistratieformulier, maar u moet ze ook toevoegen aan het profielbeheerformulier, zodat bestaande gebruikers ze kunnen bewerken.
Voeg in Areas/Identity/Pages/Account/Manage/Index.cshtml de volgende gemarkeerde markeringen toe. Sla uw wijzigingen op.
<form id="profile-form" method="post"> <div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div> <div class="form-floating mb-3"> <input asp-for="Input.FirstName" class="form-control" /> <label asp-for="Input.FirstName"></label> <span asp-validation-for="Input.FirstName" class="text-danger"></span> </div> <div class="form-floating mb-3"> <input asp-for="Input.LastName" class="form-control" /> <label asp-for="Input.LastName"></label> <span asp-validation-for="Input.LastName" class="text-danger"></span> </div> <div class="form-floating mb-3"> <input asp-for="Username" class="form-control" disabled /> <label asp-for="Username" class="form-label"></label> </div>
Breng in Areas/Identity/Pages/Account/Manage/Index.cshtml.cs de volgende wijzigingen aan om de naamtekstvakken te ondersteunen.
Voeg de eigenschappen
FirstName
enLastName
toe aan de geneste klasseInputModel
: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; } /// <summary> /// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used /// directly from your code. This API may change or be removed in future releases. /// </summary> [Phone] [Display(Name = "Phone number")] public string PhoneNumber { get; set; } }
Neem de gemarkeerde wijzigingen op in de methode
LoadAsync
:private async Task LoadAsync(RazorPagesPizzaUser 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 }; }
De voorgaande code biedt ondersteuning voor het ophalen van de voor- en achternaam voor weergave in de overeenkomstige tekstvakken op het profielbeheerformulier.
Neem de gemarkeerde wijzigingen op in de methode
OnPostAsync
. Sla uw wijzigingen op.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) { StatusMessage = "Unexpected error when trying to set phone number."; return RedirectToPage(); } } await _signInManager.RefreshSignInAsync(user); StatusMessage = "Your profile has been updated"; return RedirectToPage(); }
De voorgaande code ondersteunt het bijwerken van de voor- en achternaam in de tabel
AspNetUsers
van de database.
De afzender van de bevestigingsmail configureren
De eerste keer dat u de app hebt getest, hebt u een gebruiker geregistreerd en vervolgens op een koppeling geklikt om te simuleren dat het e-mailadres van de gebruiker wordt bevestigd. Als u een bevestigingsmail wilt verzenden, moet u een implementatie maken van IEmailSender en registreren in het systeem voor afhankelijkheidsinjectie. Om het eenvoudig te houden, verzendt uw implementatie in deze les geen e-mail naar een SMTP-server (Simple Mail Transfer Protocol). Hiermee wordt alleen de e-mailinhoud naar de console geschreven.
Omdat u het e-mailbericht in tekst zonder opmaak in de console wilt weergeven, moet u het gegenereerde bericht wijzigen om html-gecodeerde tekst uit te sluiten. Zoek in gebieden/identiteit/pagina's/account/Register.cshtml.cs de volgende code:
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
Wijzig dit in:
await _emailSender.SendEmailAsync(Input.Email, "Confirm your email", $"Please confirm your account by visiting the following URL:\r\n\r\n{callbackUrl}");
Klik in het deelvenster Explorer met de rechtermuisknop op de map RazorPagesPizza\Services en maak een nieuw bestand met de naam EmailSender.cs. Open bestand en voeg de volgende code toe:
using Microsoft.AspNetCore.Identity.UI.Services; namespace RazorPagesPizza.Services; public class EmailSender : IEmailSender { public EmailSender() {} public Task SendEmailAsync(string email, string subject, string htmlMessage) { Console.WriteLine(); Console.WriteLine("Email Confirmation Message"); Console.WriteLine("--------------------------"); Console.WriteLine($"TO: {email}"); Console.WriteLine($"SUBJECT: {subject}"); Console.WriteLine($"CONTENTS: {htmlMessage}"); Console.WriteLine(); return Task.CompletedTask; } }
Met de voorgaande code wordt een implementatie gemaakt van IEmailSender die de inhoud van het bericht naar de console schrijft. In een echte implementatie
SendEmailAsync
maakt u verbinding met een externe e-mailservice of een andere actie om e-mail te verzenden.Voeg in Program.cs de gemarkeerde regels toe:
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using RazorPagesPizza.Areas.Identity.Data; using Microsoft.AspNetCore.Identity.UI.Services; using RazorPagesPizza.Services; var builder = WebApplication.CreateBuilder(args); var connectionString = builder.Configuration.GetConnectionString("RazorPagesPizzaAuthConnection"); builder.Services.AddDbContext<RazorPagesPizzaAuth>(options => options.UseSqlServer(connectionString)); builder.Services.AddDefaultIdentity<RazorPagesPizzaUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<RazorPagesPizzaAuth>(); // Add services to the container. builder.Services.AddRazorPages(); builder.Services.AddTransient<IEmailSender, EmailSender>(); var app = builder.Build();
Het voorgaande registreert
EmailSender
zich als eenIEmailSender
in het afhankelijkheidsinjectiesysteem.
De wijzigingen in het registratieformulier testen
Dat is alles! Laten we de wijzigingen in het registratieformulier en de bevestigingsmail testen.
Zorg ervoor dat u al uw wijzigingen hebt opgeslagen.
Bouw in het terminalvenster het project en voer de app uit met
dotnet run
.Ga in uw browser naar de app. Selecteer Afmelden als u bent aangemeld.
Selecteer Registreren en gebruik het bijgewerkte formulier om een nieuwe gebruiker te registreren.
Notitie
De validatiebeperkingen voor de velden Voornaam en Achternaam weerspiegelen de gegevensaantekeningen op de eigenschappen
FirstName
enLastName
vanInputModel
.Nadat u zich hebt geregistreerd, wordt u omgeleid naar het bevestigingsscherm Registreren. Schuif in het terminalvenster omhoog om de console-uitvoer te vinden die er ongeveer als volgt uitziet:
Email Confirmation Message -------------------------- TO: jana.heinrich@contoso.com SUBJECT: Confirm your email CONTENTS: Please confirm your account by visiting the following URL: https://localhost:7192/Identity/Account/ConfirmEmail?<query string removed>
Navigeer met Ctrl+ naar de URL. Het bevestigingsscherm wordt weergegeven.
Notitie
Als u GitHub Codespaces gebruikt, moet u mogelijk toevoegen
-7192
aan het eerste deel van de doorgestuurde URL. Bijvoorbeeld:scaling-potato-5gr4j4-7192.preview.app.github.dev
.Selecteer Aanmelden en meld u aan met de nieuwe gebruiker. De header van de app bevat nu Hallo, [voornaam] [achternaam]!.
Klik in het deelvenster SQL Server in VS Code met de rechtermuisknop op de RazorPagesPizza-database en selecteer Nieuwe query. Voer in het tabblad dat wordt weergegeven de volgende query in en druk op Ctrl+Shift+E om deze uit te voeren.
SELECT UserName, Email, FirstName, LastName FROM dbo.AspNetUsers
Er wordt een tabblad met resultaten weergegeven die er ongeveer als volgt uitzien:
Gebruikersnaam E-mailen FirstName LastName kai.klein@contoso.com kai.klein@contoso.com jana.heinrich@contoso.com jana.heinrich@contoso.com Jana Heinrich De eerste gebruiker die is geregistreerd voordat u het schema toevoegt
FirstName
enLastName
aan het schema toevoegt. De gekoppeldeAspNetUsers
tabelrecord bevat dus geen gegevens in deze kolommen.
De wijzigingen in het profielbeheerformulier testen
U moet ook de wijzigingen testen die u hebt aangebracht in het profielbeheerformulier.
Meld u in de web-app aan met de eerste gebruiker die u hebt gemaakt.
Selecteer de koppeling Hallo, ! om naar het profielbeheerformulier te navigeren.
Notitie
De koppeling wordt niet correct weergegeven omdat de rij van de tabel
AspNetUsers
voor deze gebruiker geen waarden voorFirstName
enLastName
bevat.Voer geldige waarden in voor de Voornaam en Achternaam. Selecteer Opslaan.
De header van de app wordt nu gewijzigd in Hallo, [voornaam] [achternaam]!.
Als u de app wilt stoppen, drukt u op Ctrl+C in het terminalvenster in VS Code.
Samenvatting
In deze eenheid hebt u de identiteit aangepast om aangepaste gebruikersgegevens op te slaan. U hebt ook de bevestigings-e-mail aangepast. In de volgende les leert u meer over het implementeren van meervoudige verificatie in Identiteit.