Skip to content

Commit

Permalink
Add optional filter to AddFluentValidationAutoValidation() (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
pgauledev authored Mar 29, 2023
1 parent 21a6850 commit 5545304
Show file tree
Hide file tree
Showing 6 changed files with 487 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,31 @@ namespace FluentValidation.AspNetCore;
public class FluentValidationModelValidatorProvider : IModelValidatorProvider {
private readonly bool _implicitValidationEnabled;
private readonly bool _implicitRootCollectionElementValidationEnabled;
private readonly Func<Type, bool> _filter;

public FluentValidationModelValidatorProvider(bool implicitValidationEnabled)
: this(implicitValidationEnabled, false) {
: this(implicitValidationEnabled, false, default) {
}

public FluentValidationModelValidatorProvider(
bool implicitValidationEnabled,
bool implicitRootCollectionElementValidationEnabled) {
bool implicitRootCollectionElementValidationEnabled)
: this(implicitValidationEnabled, implicitRootCollectionElementValidationEnabled, default) {
}

public FluentValidationModelValidatorProvider(
bool implicitValidationEnabled,
bool implicitRootCollectionElementValidationEnabled,
Func<Type, bool> filter) {
_implicitValidationEnabled = implicitValidationEnabled;
_implicitRootCollectionElementValidationEnabled = implicitRootCollectionElementValidationEnabled;
_filter = filter;
}

public virtual void CreateValidators(ModelValidatorProviderContext context) {
context.Results.Add(new ValidatorItem {
IsReusable = false,
Validator = new FluentValidationModelValidator(_implicitValidationEnabled, _implicitRootCollectionElementValidationEnabled),
Validator = new FluentValidationModelValidator(_implicitValidationEnabled, _implicitRootCollectionElementValidationEnabled, _filter),
});
}
}
Expand All @@ -63,16 +72,25 @@ public virtual void CreateValidators(ModelValidatorProviderContext context) {
public class FluentValidationModelValidator : IModelValidator {
private readonly bool _implicitValidationEnabled;
private readonly bool _implicitRootCollectionElementValidationEnabled;
private readonly Func<Type, bool> _filter;

public FluentValidationModelValidator(bool implicitValidationEnabled)
: this(implicitValidationEnabled, false) {
: this(implicitValidationEnabled, false, default) {
}

public FluentValidationModelValidator(
bool implicitValidationEnabled,
bool implicitRootCollectionElementValidationEnabled) {
bool implicitRootCollectionElementValidationEnabled)
: this(implicitValidationEnabled, implicitRootCollectionElementValidationEnabled, default) {
}

public FluentValidationModelValidator(
bool implicitValidationEnabled,
bool implicitRootCollectionElementValidationEnabled,
Func<Type, bool> filter) {
_implicitValidationEnabled = implicitValidationEnabled;
_implicitRootCollectionElementValidationEnabled = implicitRootCollectionElementValidationEnabled;
_filter = filter;
}

public virtual IEnumerable<ModelValidationResult> Validate(ModelValidationContext mvContext) {
Expand Down Expand Up @@ -140,6 +158,12 @@ public virtual IEnumerable<ModelValidationResult> Validate(ModelValidationContex
}

protected bool ShouldSkip(ModelValidationContext mvContext) {
//Apply custom filter (if specified)
//validation will be skipped unless we match on this filter
if (_filter != null && !_filter.Invoke(mvContext.ModelMetadata.ModelType)) {
return true;
}

// Skip if there's nothing to process.
if (mvContext.Model == null) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,15 @@ public class FluentValidationAutoValidationConfiguration {
/// Setting this to true will disable DataAnnotations and only run FluentValidation.
/// </summary>
public bool DisableDataAnnotationsValidation { get; set; }


/// <summary>
/// When specified, automatic validation will only apply to the types matched by the filter.
/// If the filter does not match, automatic validation will not be applied. This can be useful
/// for specific situations where you want to opt in/out of automatic validation
/// Example: Filter = type => type == typeof(Model)
/// </summary>
public Func<Type, bool> Filter { get; set; }
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ public static IServiceCollection AddFluentValidationAutoValidation(this IService
if (!options.ModelValidatorProviders.Any(x => x is FluentValidationModelValidatorProvider)) {
options.ModelValidatorProviders.Insert(0, new FluentValidationModelValidatorProvider(
config.ImplicitlyValidateChildProperties,
config.ImplicitlyValidateRootCollectionElements));
config.ImplicitlyValidateRootCollectionElements,
config.Filter));
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,22 @@ public async Task<ActionResult> UpdateModel() {
return TestResult();
}

public ActionResult AutoFilter(AutoFilterModel test) {
return TestResult();
}

public ActionResult AutoFilterParent(AutoFilterParentModel test) {
return TestResult();
}

public ActionResult AutoFilterRootCollection(List<AutoFilterModel> test) {
return TestResult();
}

public ActionResult AutoFilterParentWithCollection(AutoFilterParentWithCollectionModel test) {
return TestResult();
}

private ActionResult TestResult() {
var errors = new List<SimpleError>();

Expand Down
Loading

0 comments on commit 5545304

Please sign in to comment.