I've managed to set up SignUp and LogIn for my project with ASP.NET Core Identity. Everything works fine but there is a small thing really bugging me.
Since it is a simple project I don't want to configure account confirmation by really sending email to the user so I'm using the default templates, the user is redirected to the Account.RegisterConfirmation where they can select a link to have the account confirmed which redirects the user to the /Identity/Account/ConfirmEmail which is a blank page with the title only. I don't like it. After selecting a link to confirm the account I'd like to redirect the user to the /Account/Login. But where do I set that up?
This is what I've tried so far: Add>New Scaffolded Item>Identity>Account/ConfirmEmail(file to override) and I now I have ConfirmEmail.cshtml.cs:
[AllowAnonymous]
public class ConfirmEmailModel : PageModel
{
private readonly UserManager<IdentityUser> _userManager;
public ConfirmEmailModel(UserManager<IdentityUser> userManager)
{
_userManager = userManager;
}
[TempData]
public string StatusMessage { get; set; }
public async Task<IActionResult> OnGetAsync(string userId, string code)
{
if (userId == null || code == null)
{
return RedirectToPage("/Index");
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
return NotFound($"Unable to load user with ID '{userId}'.");
}
code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code));
var result = await _userManager.ConfirmEmailAsync(user, code);
StatusMessage = result.Succeeded ? "Thank you for confirming your email." : "Error confirming your email.";
return Page();
}
}
Changing return Page();
to return RedirectToPage("/Account/Login");
results in InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager`1[Microsoft.AspNetCore.Identity.IdentityUser]' while attempting to activate 'Project.Areas.Identity.Pages.Account.ConfirmEmailModel'.
Where do I set up the return url to /Account/Login after the email is confirmed?
I also tried without Scaffolding and overriding Account/ConfirmEmail, in Register.cshtml.cs there is
var callbackUrl = Url.Page(
"/Account/ConfirmEmail",
pageHandler: null,
values: new { area = "Identity", userId = user.Id, code = code, returnUrl = returnUrl },
protocol: Request.Scheme);
and I tried changing returnUrl = returnUrl
to returnUrl = "~/Account/Login"
, it didn't work.
**** UPDATE ***
Since I don't need email confirmation for such a simple project I just added this
options.SignIn.RequireConfirmedAccount = false
to the Startup class so account confirmation nor email confirmation is needed.
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores<ProjectContext>();
services.Configure<IdentityOptions>(options =>
{
options.SignIn.RequireConfirmedEmail = false;
options.SignIn.RequireConfirmedAccount = false;
});
I'm using the default templates, the user is redirected to the Account.RegisterConfirmation
In default code of configuring Identity service, we would find that RequireConfirmedAccount
option is set to true
, like below.
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
And we can find that user will be redirected to RegisterConfirmation
page after user account is create in RegisterModel
class page handler.
if (_userManager.Options.SignIn.RequireConfirmedAccount)
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
else
{
it is a simple project I don't want to configure account confirmation
If you do not need account confirmation, you could not set RequireConfirmedAccount property (defaults to false) of SignInOptions while you configure Identity service.
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ProjectContext>();
Or as you did, set SignIn settings explicitly.
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores<ProjectContext>();
Besides, we can find that you call services.AddDefaultIdentity<ApplicationUser>(...)
to configure Identity service with your custom ApplicationUser
class in Startup ConfigureServices method, but you inject an instance of UserManager within ConfirmEmailModel
class using UserManager<IdentityUser>
(should use UserManager<ApplicationUser>
), which cause the exception.