I created a Blazor Web App and set its Authentication type to Individual Accounts.
Now I want to localize its Register page. The rendermode of the Register page is InteractiveServer.
The default InputModel is just like this and it works well:
<code>private sealed class InputModel
[Display(Name = "UserName")]
public string UserName { get; set; } = "";
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; } = "";
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; } = "";
<code>private sealed class InputModel
{
[Required]
[Display(Name = "UserName")]
public string UserName { get; set; } = "";
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; } = "";
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; } = "";
}
</code>
private sealed class InputModel
{
[Required]
[Display(Name = "UserName")]
public string UserName { get; set; } = "";
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
[Display(Name = "Password")]
public string Password { get; set; } = "";
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; } = "";
}
And I modify the code for localizing like this:
<code>private sealed class InputModel
[Required(ErrorMessageResourceName = "ErrorMessageUserNameRequire", ErrorMessageResourceType = typeof(Register))]
public string UserName { get; set; } = "";
[Required(ErrorMessageResourceName = "ErrorMessagePasswordRequire", ErrorMessageResourceType = typeof(Register))]
[StringLength(20, ErrorMessage = "ErrorMessagePasswordLength",ErrorMessageResourceType =typeof(Register), MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; } = "";
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "ErrorMessageConfirmPasswordCompare", ErrorMessageResourceType = typeof(Register))]
public string ConfirmPassword { get; set; } = "";
<code>private sealed class InputModel
{
[Required(ErrorMessageResourceName = "ErrorMessageUserNameRequire", ErrorMessageResourceType = typeof(Register))]
public string UserName { get; set; } = "";
[Required(ErrorMessageResourceName = "ErrorMessagePasswordRequire", ErrorMessageResourceType = typeof(Register))]
[StringLength(20, ErrorMessage = "ErrorMessagePasswordLength",ErrorMessageResourceType =typeof(Register), MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; } = "";
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "ErrorMessageConfirmPasswordCompare", ErrorMessageResourceType = typeof(Register))]
public string ConfirmPassword { get; set; } = "";
}
</code>
private sealed class InputModel
{
[Required(ErrorMessageResourceName = "ErrorMessageUserNameRequire", ErrorMessageResourceType = typeof(Register))]
public string UserName { get; set; } = "";
[Required(ErrorMessageResourceName = "ErrorMessagePasswordRequire", ErrorMessageResourceType = typeof(Register))]
[StringLength(20, ErrorMessage = "ErrorMessagePasswordLength",ErrorMessageResourceType =typeof(Register), MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; } = "";
[DataType(DataType.Password)]
[Compare("Password", ErrorMessage = "ErrorMessageConfirmPasswordCompare", ErrorMessageResourceType = typeof(Register))]
public string ConfirmPassword { get; set; } = "";
}
After the program ran, if I click the register button, the Validator works well without any exception.
However, if I input the username and password without inputting any confirm password, then click the register button. The browser reports the exception as below:
<code>[2024-04-25T23:14:45.687Z] Error: System.InvalidOperationException: Both ErrorMessageResourceType and ErrorMessageResourceName need to be set on this attribute.
at System.ComponentModel.DataAnnotations.ValidationAttribute.SetupResourceAccessor()
at System.ComponentModel.DataAnnotations.StringLengthAttribute.FormatErrorMessage(String name)
at System.ComponentModel.DataAnnotations.ValidationAttribute.CreateFailedValidationResult(ValidationContext validationContext)
at System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext)
at System.ComponentModel.DataAnnotations.Validator.TryValidate(Object value, ValidationContext validationContext, ValidationAttribute attribute, ValidationError& validationError)
at System.ComponentModel.DataAnnotations.Validator.GetValidationErrors(Object value, ValidationContext validationContext, IEnumerable`1 attributes, Boolean breakOnFirstError)
at System.ComponentModel.DataAnnotations.Validator.TryValidateProperty(Object value, ValidationContext validationContext, ICollection`1 validationResults)
at Microsoft.AspNetCore.Components.Forms.EditContextDataAnnotationsExtensions.DataAnnotationsEventSubscriptions.OnFieldChanged(Object sender, FieldChangedEventArgs eventArgs)
at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValue(TValue value)
at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValueAsString(String value)
at Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions.<>c__DisplayClass64_0`1.<CreateBinderCore>b__0(ChangeEventArgs e)
at InvokeStub_Action`1.Invoke(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
<code>[2024-04-25T23:14:45.687Z] Error: System.InvalidOperationException: Both ErrorMessageResourceType and ErrorMessageResourceName need to be set on this attribute.
at System.ComponentModel.DataAnnotations.ValidationAttribute.SetupResourceAccessor()
at System.ComponentModel.DataAnnotations.StringLengthAttribute.FormatErrorMessage(String name)
at System.ComponentModel.DataAnnotations.ValidationAttribute.CreateFailedValidationResult(ValidationContext validationContext)
at System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext)
at System.ComponentModel.DataAnnotations.Validator.TryValidate(Object value, ValidationContext validationContext, ValidationAttribute attribute, ValidationError& validationError)
at System.ComponentModel.DataAnnotations.Validator.GetValidationErrors(Object value, ValidationContext validationContext, IEnumerable`1 attributes, Boolean breakOnFirstError)
at System.ComponentModel.DataAnnotations.Validator.TryValidateProperty(Object value, ValidationContext validationContext, ICollection`1 validationResults)
at Microsoft.AspNetCore.Components.Forms.EditContextDataAnnotationsExtensions.DataAnnotationsEventSubscriptions.OnFieldChanged(Object sender, FieldChangedEventArgs eventArgs)
at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValue(TValue value)
at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValueAsString(String value)
at Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions.<>c__DisplayClass64_0`1.<CreateBinderCore>b__0(ChangeEventArgs e)
at InvokeStub_Action`1.Invoke(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
</code>
[2024-04-25T23:14:45.687Z] Error: System.InvalidOperationException: Both ErrorMessageResourceType and ErrorMessageResourceName need to be set on this attribute.
at System.ComponentModel.DataAnnotations.ValidationAttribute.SetupResourceAccessor()
at System.ComponentModel.DataAnnotations.StringLengthAttribute.FormatErrorMessage(String name)
at System.ComponentModel.DataAnnotations.ValidationAttribute.CreateFailedValidationResult(ValidationContext validationContext)
at System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext)
at System.ComponentModel.DataAnnotations.Validator.TryValidate(Object value, ValidationContext validationContext, ValidationAttribute attribute, ValidationError& validationError)
at System.ComponentModel.DataAnnotations.Validator.GetValidationErrors(Object value, ValidationContext validationContext, IEnumerable`1 attributes, Boolean breakOnFirstError)
at System.ComponentModel.DataAnnotations.Validator.TryValidateProperty(Object value, ValidationContext validationContext, ICollection`1 validationResults)
at Microsoft.AspNetCore.Components.Forms.EditContextDataAnnotationsExtensions.DataAnnotationsEventSubscriptions.OnFieldChanged(Object sender, FieldChangedEventArgs eventArgs)
at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValue(TValue value)
at Microsoft.AspNetCore.Components.Forms.InputBase`1.set_CurrentValueAsString(String value)
at Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions.<>c__DisplayClass64_0`1.<CreateBinderCore>b__0(ChangeEventArgs e)
at InvokeStub_Action`1.Invoke(Object, Span`1)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion(Task task)
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
It does not provide details on which line of code the problem occurs. Although I guess there may be a problem with the Compare tag, I can’t figure out what the problem is.
What’s wrong with my code?