Reputation: 1443
I'm having a problem using the default ASP.NET Identity service. Everything is working but when trying to register for an account, if the password complexity is not met, no error messages are displayed.
I ran the debugger, and below is the error that is thrown:
result {Failed : PasswordTooShort,PasswordRequiresDigit,PasswordRequiresUpper,PasswordRequiresUniqueChars} Microsoft.AspNetCore.Identity.IdentityResult
The error message is not passed into the view to be displayed on the Password field. How do you pass the errors into the view? I can manually create a modelstate error but would like the pre-configured messages to be passed in instead.
**Update, I am able to pull in the error messages but trying to solve how to pass all messages into the view. Right now, the view only displays the first error message. Do I need to loop through all the error messages in the view to do that? If so, what would be the best approach?
I have configured the services as below in my startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>();
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 6;
});
services.AddTransient<IFeedbackRepository, FeedbackRepository>();
services.AddTransient<IPieRepository, PieRepository>();
services.AddMvc();
}
My Account controller is configured as below:
public class AccountController : Controller
{
private readonly SignInManager<IdentityUser> _signInManager;
private readonly UserManager<IdentityUser> _userManager;
public AccountController(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
public IActionResult Register()
{
return View(new LoginViewModel());
}
[HttpPost]
public async Task<IActionResult> Register(LoginViewModel loginViewModel)
{
if (ModelState.IsValid)
{
var user = new IdentityUser() { UserName = loginViewModel.UserName };
var result = await _userManager.CreateAsync(user, loginViewModel.Password);
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
else
{
var errList = "";
var error = result.Errors.ToList(); //convert to list
foreach (var err in error) //iterate through individual error
{
this.ModelState.AddModelError("Password", err.Description); //add error to modelstate
//errList += string.Join(", ", err.Description);
}
//this.ModelState.AddModelError("Password", errList);
}
}
return View(loginViewModel);
}
The loginviewmodel is configured as:
public class LoginViewModel
{
[Key]
[Required]
[Display(Name ="User Name")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}
The View for register is configured as:
@model LoginViewModel
<h2>Register</h2>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Register" asp-controller="Account" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="UserName" class="control-label"></label>
<input asp-for="UserName" class="form-control" />
<span asp-validation-for="UserName" class="text-danger"></span><br />
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Register" class="btn btn-default" />
</div>
</form>
</div>
</div>
Upvotes: 2
Views: 3609
Reputation: 48230
I can't validate this easily (no compiler/vs at hand) but you could try to add the model error in an explicit way before you render the view again
if (result.Succeeded)
{
return RedirectToAction("Index", "Home");
}
else
{
var error = string.Join( ", ", result.Errors );
this.ModelState.AddModelError( "Password", error );
}
Upvotes: 2