Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] OnFieldChanged validates field using validator for owning instance type, not the one for EditContext.Model type #235

Open
hakenr opened this issue Sep 24, 2024 · 0 comments
Labels
Bug Something isn't working Triage Issue needs to be triaged

Comments

@hakenr
Copy link

hakenr commented Sep 24, 2024

Describe the bug
Assume we have a complex type from this documentation: https://docs.fluentvalidation.net/en/latest/start.html#complex-properties
There is a Customer class with an Address property and two validators: CustomerValidator and AddressValidator.

Let’s remove this line from the CustomerValidator:

public class CustomerValidator : AbstractValidator<Customer> 
{
  public CustomerValidator()
  {
    RuleFor(customer => customer.Name).NotNull();
-   RuleFor(customer => customer.Address).SetValidator(new AddressValidator());
  }
}

The AddressValidator still exists:

public class AddressValidator : AbstractValidator<Address> 
{
  public AddressValidator()
  {
    RuleFor(address => address.Postcode).NotNull();
    // etc.
  }
}

Now, when you create this type of UI (shortened for brevity):

<EditForm Model="company">
  <FluentValidationValidator />
  <InputText @bind-Value="company.Address.Postcode" />

The FluentValidationValidator validates the Postcode field using the AddressValidator, even though the CompanyValidator for the Model does not reference the AddressValidator, and companyValidator.Validate() does not use the AddressValidator. The Postcode field should not be validated in this case.

Expected behavior
The validator for the Model (CustomerValidator) should be used for all field validations, company.Address.Postcode should not be validated as CustomerValidator does not reference AddressValidator.

Additional context

private static async Task ValidateField(EditContext editContext,
ValidationMessageStore messages,
FieldIdentifier fieldIdentifier,
IServiceProvider serviceProvider,
bool disableAssemblyScanning,
IValidator? validator = null)
{
var properties = new[] { fieldIdentifier.FieldName };
var context = new ValidationContext<object>(fieldIdentifier.Model, new PropertyChain(), new MemberNameValidatorSelector(properties));
validator ??= GetValidatorForModel(serviceProvider, fieldIdentifier.Model, disableAssemblyScanning);
if (validator is not null)
{
var validationResults = await validator.ValidateAsync(context);
messages.Clear(fieldIdentifier);
messages.Add(fieldIdentifier, validationResults.Errors.Select(error => error.ErrorMessage));
editContext.NotifyValidationStateChanged();
}
}

I believe the issue is in how the ValidateField() method is implemented. It uses fieldIdentifier.Model directly and does not take editContext.Model into account. The implementation won’t be trivial (you cannot simply replace fieldIdentifier.Model with editContext.Model as someone has already tried), but it is doable.

Related items:

cc @jirikanda

@hakenr hakenr added Bug Something isn't working Triage Issue needs to be triaged labels Sep 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Triage Issue needs to be triaged
Projects
None yet
Development

No branches or pull requests

1 participant