Table of Contents (top down ↓)
The Plan of Implmentation
Let's have a look at the plan.
First of all we will ask the user to enter his email and submit the form to our server.
On the server side this email will be used to obtain the IdentityUser record. Then, this instance will be used to generate an email confirmation token. And, the token will, in turn, be used to construct the email confirmation link which will be emailed or sent to the user in an sms message.
Video Explanation (see it happen!)
Please watch the following youtube video:
Add the Resend EMail Confirmation Page
Our first step is to add a page for the resend email functionality. So, locate the auth area and add a page called ResendEMailConfirmation.
We can now examine the markup for this page.
// Areas -> Auth -> Pages -> ResendEMailConfirmation.cshtml @page @model MyRazorApp.Areas.Auth.Pages.ResendEMailConfirmationModel @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers <h1>Please type EMail to Receive Confirmation EMail</h1> <div style="color:red" asp-validation-summary="All"></div> <form method="post"> <table> <tr> <td> <label asp-for="UserID"></label> </td> <td> <input asp-for="UserID" /> </td> <td> <span asp-validation-for="UserID"></span> </td> </tr> <tr> <td colspan="2" style="text-align:right"> <input type="submit" value="Send!" /> </td> </tr> </table> </form>
First we have the customary directives for model, addTagHelper.
Then we have a tag for the validation summary.
An html table has been used for creating the form. The first tr is for the email input text box. This input is connected to a bind property called UserID
. This property will carry the email to the server side.
Then, we have a submit button. We have kept the form brief and simple by avoiding any css and javascript, which can always be added with the help of designer teams.
Next, let us come to the backing class. Double click the ResendEMailConfirmation.cshtml.cs file to open the backing class.
This is the ResendEMailConfirmationModel class.
// Areas -> Auth -> Pages -> ResendEMailConfirmation.cshtml.cs // namespaces using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.WebUtilities; using System.ComponentModel.DataAnnotations; using System.Text; namespace MyRazorApp.Areas.Auth.Pages { [AllowAnonymous] public class ResendEMailConfirmationModel : PageModel { // user id, i.e., email [BindProperty] [Required] [DataType(DataType.EmailAddress)] public String? UserID { get; set; } // UserManager service private readonly UserManager<IdentityUser> _um; // dependency injection public ResendEMailConfirmationModel(UserManager<IdentityUser> um) { _um = um; } public async Task<IActionResult> OnPostAsync() { if (!ModelState.IsValid) { return Page(); } IdentityUser user = await _um.FindByEmailAsync(UserID); // if user not registered, or bad entry if (null == user) { ModelState.AddModelError(string.Empty, "EMail not found."); return Page(); } // generate the token var code = await _um.GenerateEmailConfirmationTokenAsync(user); // encode as base64 code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code)); // create the link and email or send by sms /* String link = Url.Page( "/ConfirmAccount", null, new { area = "Auth", userID = userID, code = code }, Request.Scheme); */ // during testing - we use a test page return RedirectToPage("EMailTestPage", new { userId = user.Id, code = code }); } } }
First we have the namespace directives.
The class has been marked as [AllowAnonymous] so that it is publically available.
Then we have UserID as the bind property for the email of the user.
Constructor based dependency injection has been used to obtain the UserManager service. This service is used to obtain the email confirmation token. We have cached it as a readonly member.
The OnPost method executes when the user submits and posts the form.
The FindByEmailAsync
method is used to obtain the IdentityUser
.
If the user cannot be found, then a suitable message is shown.
The confirmation token is obtained through the GenerateEmailConfirmationTokenAsync
function.
Then it is encoded as a base64 string.
As you can see in the commented part, the link can now be generated by using the Url.Page
function. In a real world application this link would be emailed at this point.
But since we are in a tutorial, we can redirect the user to an email test page and show the link there. This is the same thing that we did in the previous tutorial.
For completeness, we can have a look at the email test page. Come to the solution explorer and locate the email test page.
// Pages -> EMailTestPage.cshtml @page @functions { public String? Link { get; set; } public void OnGet(String userID, String code) { Link = Url.Page( "/ConfirmAccount", null, new { area = "Auth", userID = userID, code = code }, Request.Scheme); } } <h1>Test EMail</h1> <p> NOTE: in real application this link is sent in an email to the user. He has to click the link for email verification. </p> <h2>Please click to confirm your email</h2> <a href="@(Link)">Click to Confirm</a>
Double click to open it. As you can see, the link is generated in the OnGet method, and displayed through an anchor tag.
Run the Project
Run the project and visit the login page. Click the ResendEMailConfirmation link. We are redirected to the resend email confirmation page. Type a registered email, and click the send button. That takes us to the test email page where we can confirm our account. In a real application there will be no test page. Instead of that the user would be emailed the link. Thanks!
Similar Posts
This Blog Post/Article "(C# ASP.NET Core) Resending an Account Verification EMail in Identity based Authentication" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.