Closed
Description
var compareAttribute = new CompareAttribute("Test");
compareAttribute.IsValid("foo");
Stack trace:
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
at System.ComponentModel.DataAnnotations.CompareAttribute.IsValid(Object value, ValidationContext validationContext)
at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value)
Describe the bug
I have multiple models however each model which contains Password/ConfirmPassword cause crash after setting ConfirmPassword. (EDIT: I found out its caused by CompareProperty attribute)
To Reproduce
I implemented my own ValidationContext class which validates on field changed (EditContext) all attributes per changing field.
Implementation of ValidationContext for OnFieldChanged looks like this:
void EditContext_OnFieldChanged(object sender, FieldChangedEventArgs e)
{
PropertyInfo property = Model.GetType().GetProperty(e.FieldIdentifier.FieldName);
if (property is null)
return;
IEnumerable<ValidationAttribute> attributes = property.GetCustomAttributes<ValidationAttribute>();
List<string> errors = new List<string>();
if(Errors.ContainsKey(e.FieldIdentifier.FieldName))
Errors.Remove(e.FieldIdentifier.FieldName);
foreach(ValidationAttribute attribute in attributes)
{
if (!attribute.IsValid(property.GetValue(Model)))
errors.Add(attribute.ErrorMessage);
}
if (errors.Count > 0)
Errors[e.FieldIdentifier.FieldName] = errors;
}
Crashing on this place. Only if I change field ConfirmPassword!
if (!attribute.IsValid(property.GetValue(Model)))
Debugger says e.FieldIdentifier.FieldName is "ConfirmPassword"
Model definition
[Required, Display(Name = "Password", ResourceType = typeof(Translations.Accounts)), DataType(DataType.Password)]
public string Password { get; set; }
[Required, Display(Name = "ConfirmPassword", ResourceType = typeof(Translations.Accounts)), DataType(DataType.Password), CompareProperty("Password", ErrorMessageResourceName = "Compare", ErrorMessageResourceType = typeof(Translations.Accounts))]
public string ConfirmPassword { get; set; }
Razor
<div class="form-group">
<label for="ConfirmPassword" class="control-label">@Translations.ConfirmPassword</label>
<InputText type="password" name="ConfirmPassword" class="@($"form-control {ModelContext.DisplayError(x => x.ConfirmPassword)}")" placeholder="@Translations.ConfirmPassword" required="@(!Edit || !string.IsNullOrEmpty(Model.Password))" minlength="@Policy.MinLength" maxlength="@Policy.MaxLength" @bind-Value="Model.ConfirmPassword" />
@if (ModelContext.HasError(x => x.ConfirmPassword))
{
<i class="fas fa-exclamation-triangle invalid-feedback"></i>
<span class="invalid-feedback"><ValidationMessage For="@(() => Model.ConfirmPassword)" /></span>
}
</div>
Exceptions (if any)
blazor.webassembly.js:1 crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100]
Unhandled exception rendering component: Object reference not set to an instance of an object.
System.NullReferenceException: Object reference not set to an instance of an object.
at (wrapper managed-to-native) System.Reflection.RuntimeMethodInfo.InternalInvoke(System.Reflection.RuntimeMethodInfo,object,object[],System.Exception&)
at System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) <0x2877a78 + 0x000ce> in <filename unknown>:0
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Components.ComponentBase.CallStateHasChangedOnAsyncCompletion (System.Threading.Tasks.Task task) <0x2ffc038 + 0x000da> in <filename unknown>:0
at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask (System.Threading.Tasks.Task taskToHandle) <0x2ffffc0 + 0x000b6> in <filename unknown>:0
Further technical details
- ASP.NET Core version 3.1.4
- VS 16.0
Any idea how to get more debug info?
Activity