I have a web form for capturing some details from a user to send to the backend. The register form has a model class called RegisterModel
that validates all the input the user enters in that form. The model state does not throw errors for the other fields when I enter input that satisfies the required conditions, but it does thrown an error for the confirm password field even though the field is not empty and matches the previous password input.
RegisterModel
:
[Required(ErrorMessage ="The password field is required")]
[MinLength(8, ErrorMessage ="The password needs to be at least eight characters long")]
[MaxLength(50, ErrorMessage ="The password length cannot exceed fifty characters")]
[RegularExpression("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\W).+$", ErrorMessage = "Password must contain at least one uppercase letter, one lowercase letter, and one special character.")]
public string Password { get; set; }
[Required(ErrorMessage = "You have to confirm the password")]
[Compare("Password", ErrorMessage = "The passwords do not match")]
public string Confirmpassword { get; set; }
Code data for the register form with all the required controller and action name attributes
Register form:
@model Christian_Social.Models.RegisterModel
<div class="container">
<div class="text-center">
<h4 style="color:blue">Create a new account to proceed</h4>
<div class="row justify-content-center">
<div class="col-md-6">
<div class="card mt-5">
<div class="card-body">
<form asp-controller="Register" asp-action="CreateEntry" method="post">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username"asp-for=username required>
<span class="text-danger" style="color:red" asp-validation-for="username"></span>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" asp-for="Email" required>
<span class="text-danger" style="color:red" asp-validation-for="Email"></span>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" asp-for="Password"required>
<span class="text-danger" style="color:red" asp-validation-for="Password"></span>
</div>
<div class="mb-3">
<label for="confirm-password" class="form-label">Confirm Password</label>
<input type="password" class="form-control" id="confirm-password" name="confirm-password" asp-for="Confirmpassword" required>
<span class="text-danger" style="color:red" asp-validation-for="Confirmpassword"></span>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
Here is how I am handling logic from the controller when the form is submitted:
RegisterController
:
public class RegisterController : Controller
{
private readonly DatabaseContext databaseContext;
public RegisterController(DatabaseContext dataContext)
{
databaseContext = dataContext;
}
public IActionResult CreateEntry(RegisterModel registerModel)
{
if (ModelState.IsValid)
{
// return the account created successfully page
// encrypt the password, since passwords are private
var encryptedPassword = BCrypt.Net.BCrypt.HashPassword(registerModel.Password);
var userName = registerModel.username;
var email = registerModel.Email;
// create a new database entity
var entity = new User
{
Username = userName,
Email = email,
Password = encryptedPassword,
};
// make sure you are not adding duplicate entries
var user = databaseContext.Users.Where(p=>p.Email == email).FirstOrDefault();
if (user == null)
{
// entry does not exist, add a new one
databaseContext.Add(entity);
// save changes
databaseContext.SaveChanges();
return View("~Views/Home/Index");
}
else
{
// add errors to the model state and return the same view
ModelState.AddModelError("Email", "That email is already taken");
return View("~Views/Home/Register", registerModel);
}
}
else
{
return View("~/Views/Home/Register.cshtml", registerModel);
}
}
}
Why is my form returning the error when the field has a password and it matches the entry in the password field?
The names of the form fields should match the property names in the RegisterModel. Specifically, the name attribute for the confirm password field should match the model property name.
<div class="mb-3">
<label for="confirm-password" class="form-label">Confirm Password</label>
<input type="password" class="form-control" id="confirm-password" name="Confirmpassword" asp-for="Confirmpassword" required>
<span class="text-danger" style="color:red" asp-validation-for="Confirmpassword"></span>
</div>
Also it requires client-side validation scripts included in your view. If not added we need to add these
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.5.1.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.19.1/jquery.validate.min.js"></script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate.unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>
Also check the casing of the property names in your model matches the form field names.