Do you want to allow user to login with either Username or Email address? ASP.NET Identity uses Username for Signin verification and In default Core template, Email is used as Username. In this post, we will change ASP.NET Core Identity setup to allow both Username and Email on login.
Assumptions:
1. Username is unique for each user. It is either input by user or generated by application on registration.
2. No @ symbol allowed in Username.
The default LoginViewModel:
public class LoginViewModel { [Required] [EmailAddress] public string Email { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } [Display(Name = "Remember me?")] public bool RememberMe { get; set; } }
Remove EmailAddress annotation and define Display text
public class LoginViewModel { [Required] [Display(Name = "Username/Email")] public string Email { get; set; } [Required] [DataType(DataType.Password)] public string Password { get; set; } [Display(Name = "Remember me?")] public bool RememberMe { get; set; } }
In AccountController, The default Login action is as follow
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) { ViewData["ReturnUrl"] = returnUrl; if (ModelState.IsValid) { // This doesn't count login failures towards account lockout // To enable password failures to trigger account lockout, set lockoutOnFailure: true var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
As user can enter either Username or Email, so we will make @ character for validation criteria. Here is the flow to be implemented:
1. If in the string @ is present, apply Email validation else apply Username format validation.
2. In case of valid Email, first we need to get Username. As it is considered that Username is unique so we can get it with userManager.FindByEmailAsync method.
3. Use Username for SignIn verification.
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) { ViewData["ReturnUrl"] = returnUrl; if (model.Email.IndexOf('@') > -1) { //Validate email format string emailRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" + @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" + @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"; Regex re = new Regex(emailRegex); if (!re.IsMatch(model.Email)) { ModelState.AddModelError("Email", "Email is not valid"); } } else { //validate Username format string emailRegex = @"^[a-zA-Z0-9]*$"; Regex re = new Regex(emailRegex); if (!re.IsMatch(model.Email)) { ModelState.AddModelError("Email", "Username is not valid"); } } if (ModelState.IsValid) { var userName = model.Email; if (userName.IndexOf('@') > -1) { var user = await _userManager.FindByEmailAsync(model.Email); if (user == null) { ModelState.AddModelError(string.Empty, "Invalid login attempt."); return View(model); } else { userName = user.UserName; } } var result = await _signInManager.PasswordSignInAsync(userName, model.Password, model.RememberMe, lockoutOnFailure: false);
No special need to change in View. Run the application and test login with Email or Username.
Enjoy ASP.NET Core!!
I love your blog.. very nice colors & theme. Did you make this website yourself or
did you hire someone to do it for you? Plz respond as I’m looking to create my own blog and would like to find out where u got this from.
kudos
Nice and simple, thanks!
Thanks for this! Many internet sources for ASP/MVC just give solutions as custom classes. This is the first I’ve found that helps me alter the template.