I have a Blazor server app that has a form with two password inputs, "new password" and "confirm password". I m using DataAnnotations Compare
attribute to validate that the two match. I ve also tried the CompareProperty
attribute from the experimental NuGet package Microsoft.AspNetCore.Components.DataAnnotations.Validation
, but the behavior is the same.
The sample page below is able to reproduce the error in Chrome and Edge. Testing steps:
- Generate a random password using the browser password generation tool (in Chrome, right click -> Suggest password...). Both password fields should be auto filled in with the generated password.
- In the "new password" field, add one character at the end. This updates the value in "confirm password" as well, so the values do match, but a validation failure is triggered.
- To remove the validation failure, delete the last character in "confirm password", tab out of the field, then go back to the field and add the same character back in. This time, the validation is successful.
Just from personal experience, I sometimes add extra characters to the end of passwords suggested by Chrome, mostly to satisfy complexity requirements the generated password didn t meet. So this form behavior will be problematic if my users do the same. Anyone know what s going on here and how to solve it?
Index.razor:
@page "/"
@using System.ComponentModel.DataAnnotations;
<PageTitle>Index</PageTitle>
<EditForm name="passwordForm" Model="MyModel" OnSubmit="@SubmitPasswordForm">
<DataAnnotationsValidator />
<div class="form-group">
<label for="NewPassword">New Password</label>
<InputText @bind-Value="MyModel.NewPassword" class="form-control" id="NewPassword" name="NewPassword" type="password" autocomplete="new-password"></InputText>
<ValidationMessage For="@(() => MyModel.NewPassword)" />
</div>
<div class="form-group">
<label for="ConfirmNewPassword">Confirm Password</label>
<InputText @bind-Value="MyModel.ConfirmPassword" class="form-control" id="ConfirmNewPassword" name="ConfirmNewPassword" type="password" autocomplete="new-password"></InputText>
<ValidationMessage For="@(() => MyModel.ConfirmPassword)" />
</div>
<input id="submitResetPassword" type="submit" class="btn btn-default" value="Reset Password" />
</EditForm>
@code {
private Model MyModel { get; set; } = new();
private void SubmitPasswordForm()
{
// Do something with the password
}
private class Model
{
[Required]
public string? NewPassword { get; set; }
[Required]
[Compare(nameof(NewPassword))]
// or [CompareProperty(nameof(NewPassword))]
public string? ConfirmPassword { get; set; }
}
}