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

Deprecation of various MVC-specific validation strategies #1960

Closed
JeremySkinner opened this issue Jun 18, 2022 · 0 comments
Closed

Deprecation of various MVC-specific validation strategies #1960

JeremySkinner opened this issue Jun 18, 2022 · 0 comments

Comments

@JeremySkinner
Copy link
Member

JeremySkinner commented Jun 18, 2022

Background

FluentValidation supports several features that only work within ASP.NET Core MVC-based projects. Back when MVC was the only way to build web applications, this seemed reasonable. However, ASP.NET now provides several alternatives to MVC (including Minimal APIs and Razor) where these features can't be used.

Our aim with FluentValidation going forward is to provide a mostly uniform experience when working with different web frameworks (as well as desktop/console apps) and we encourage developers to design their validators in a way that's agnostic of which web framework you're using. As such, we will be deprecating several MVC-specific features starting with release 11.1 including:

  • The InjectValidator method
  • Implicit validation of child properties (ImplicitlyValidateChildProperties)
  • Implicit validation of root collection elements (ImplicitlyValidateRootCollectionElements)

Deprecation of InjectValidator

The InjectValidator method allowed you to implicitly inject a child validator from the ASP.NET Service Provider.

public class PersonValidator : AbstractValidator<Person> 
{
  public PersonValidator() 
  {
    RuleFor(x => x.Address).InjectValidator();
  }
}

Assuming that the address property is of type Address, the above code would attempt to resolve an IValidator<Address> and use this to validator the Address property. This method can only be used when working with ASP.NET MVC's auto-validation feature and cannot be used in other contexts.

Instead of using InjectValidator, we instead recommend using a more traditional constructor injection approach, which is not just limited to ASP.NET MVC:

public class PersonValidator : AbstractValidator<Person> 
{
  public PersonValidator(IValidator<Address> addressValidator) 
  {
    RuleFor(x => x.Address).SetValidator(addressValidator);
  }
}

Deprecation of implicit child validation

By default, when validating complex object graphs you must explicitly specify any child validators for complex properties by using SetValidator (see the docs). However, within ASP.NET Core MVC projects you can also optionally enable implicit validation for child properties. When this is enabled, instead of having to specify child validators using SetValidator, MVC’s validation infrastructure will recursively attempt to automatically find validators for each property.

This was enabled in application startup by setting the ImplicitlyValidateChildProperties property:

services.AddMvc().AddFluentValidation(fv => 
{
 fv.ImplicitlyValidateChildProperties = true;
});

This approach to validation only works when auto-validation is enabled within MVC-specific projects and is not usable in other project types, or when MVC auto-validation is disabled. Additionally, this feature has a high maintenance burden and requires several workarounds in order to implement. As such, this approach is being deprecated. To migrate you should do the following:

Deprecation of implicit validation of root collection elements

By default, you must create a specific collection validator or enable implicit child property validation to validate a model that is of a collection type. For example, no validation of the following model will occur with the default settings unless you define a validator that inherits from AbstractValidator<List<Person>>.

public ActionResult DoSomething(List<Person> people) => Ok();

Implicit collection of root collections allows you to validate the contents of the collection without having to enable implicit child validation (above) or define a validator for List<T>.

Similarly to implicit child validation, this feature only works in the context of ASP.NET MVC's auto-validation and could be enabled in your application startup routine:

services.AddMvc().AddFluentValidation(fv => 
{
 fv.ImplicitlyValidateRootCollectionElements = true;
});

As with implicit child validation, this feature is specific to ASP.NET MVC's auto-validation and also has a high maintenance burden. As such it is being deprecated. To migrate, we recommend defining an explicit collection validator:

public class PersonCollectionValidator : AbstractValidator<List<Person>> 
{
  public PersonCollectionValidator() 
  {
    RuleForEach(self => self).SetValidator(new PersonValidator());
  }
}

Alternatively, switch to accepting a single object as the root model and expose the collection as a property instead.

@FluentValidation FluentValidation locked as resolved and limited conversation to collaborators Jun 18, 2022
@JeremySkinner JeremySkinner pinned this issue Jun 18, 2022
@JeremySkinner JeremySkinner changed the title Announcement: Deprecation of various MVC-specific validation strategies Deprecation of various MVC-specific validation strategies Jun 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant