Browse Source

Merge pull request #9549 from abpframework/maliming/IObjectValidator

Make IObjectValidator async.
pull/9703/head
Halil İbrahim Kalkan 5 years ago
committed by GitHub
parent
commit
e5bd7cd25f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      docs/en/Validation.md
  2. 7
      docs/zh-Hans/Validation.md
  3. 5
      framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs
  4. 4
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs
  5. 6
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs
  6. 8
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs
  7. 7
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs
  8. 17
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs
  9. 9
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs
  10. 6
      framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs
  11. 27
      framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs

7
docs/en/Validation.md

@ -149,8 +149,8 @@ Once ABP determines a validation error, it throws an exception of type `AbpValid
In addition to the automatic validation, you may want to manually validate an object. In this case, [inject](Dependency-Injection.md) and use the `IObjectValidator` service:
* `Validate` method validates the given object based on the validation rules and throws an `AbpValidationException` if it is not in a valid state.
* `GetErrors` doesn't throw an exception, but only returns the validation errors.
* `ValidateAsync` method validates the given object based on the validation rules and throws an `AbpValidationException` if it is not in a valid state.
* `GetErrorsAsync` doesn't throw an exception, but only returns the validation errors.
`IObjectValidator` is implemented by the `ObjectValidator` by default. `ObjectValidator` is extensible; you can implement `IObjectValidationContributor` interface to contribute a custom logic. Example:
@ -158,13 +158,14 @@ In addition to the automatic validation, you may want to manually validate an ob
public class MyObjectValidationContributor
: IObjectValidationContributor, ITransientDependency
{
public void AddErrors(ObjectValidationContext context)
public Task AddErrorsAsync(ObjectValidationContext context)
{
//Get the validating object
var obj = context.ValidatingObject;
//Add the validation errors if available
context.Errors.Add(...);
return Task.CompletedTask;
}
}
````

7
docs/zh-Hans/Validation.md

@ -130,8 +130,8 @@ namespace Acme.BookStore
除了自动验证你可能需要手动验证对象,这种情况下[注入](Dependency-Injection.md)并使用 `IObjectValidator` 服务:
* `Validate` 方法根据验证​​规则验证给定对象,如果对象没有被验证通过会抛出 `AbpValidationException` 异常.
* `GetErrors` 不会抛出异常,只返回验证错误.
* `ValidateAsync` 方法根据验证​​规则验证给定对象,如果对象没有被验证通过会抛出 `AbpValidationException` 异常.
* `GetErrorsAsync` 不会抛出异常,只返回验证错误.
`IObjectValidator` 默认由 `ObjectValidator` 实现. `ObjectValidator`是可扩展的; 可以实现`IObjectValidationContributor`接口提供自定义逻辑.
示例 :
@ -140,13 +140,14 @@ namespace Acme.BookStore
public class MyObjectValidationContributor
: IObjectValidationContributor, ITransientDependency
{
public void AddErrors(ObjectValidationContext context)
public Task AddErrorsAsync(ObjectValidationContext context)
{
//Get the validating object
var obj = context.ValidatingObject;
//Add the validation errors if available
context.Errors.Add(...);
return Task.CompletedTask;
}
}
````

5
framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs

@ -2,6 +2,7 @@ using FluentValidation;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Validation;
@ -17,7 +18,7 @@ namespace Volo.Abp.FluentValidation
_serviceProvider = serviceProvider;
}
public void AddErrors(ObjectValidationContext context)
public virtual async Task AddErrorsAsync(ObjectValidationContext context)
{
var serviceType = typeof(IValidator<>).MakeGenericType(context.ValidatingObject.GetType());
var validator = _serviceProvider.GetService(serviceType) as IValidator;
@ -26,7 +27,7 @@ namespace Volo.Abp.FluentValidation
return;
}
var result = validator.Validate((IValidationContext) Activator.CreateInstance(
var result = await validator.ValidateAsync((IValidationContext) Activator.CreateInstance(
typeof(ValidationContext<>).MakeGenericType(context.ValidatingObject.GetType()),
context.ValidatingObject));

4
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
@ -26,9 +27,10 @@ namespace Volo.Abp.Validation
Options = options.Value;
}
public void AddErrors(ObjectValidationContext context)
public Task AddErrorsAsync(ObjectValidationContext context)
{
ValidateObjectRecursively(context.Errors, context.ValidatingObject, currentDepth: 1);
return Task.CompletedTask;
}
protected virtual void ValidateObjectRecursively(List<ValidationResult> errors, object validatingObject, int currentDepth)

6
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs

@ -1,7 +1,9 @@
namespace Volo.Abp.Validation
using System.Threading.Tasks;
namespace Volo.Abp.Validation
{
public interface IMethodInvocationValidator
{
void Validate(MethodInvocationValidationContext context);
Task ValidateAsync(MethodInvocationValidationContext context);
}
}

8
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs

@ -1,7 +1,9 @@
namespace Volo.Abp.Validation
using System.Threading.Tasks;
namespace Volo.Abp.Validation
{
public interface IObjectValidationContributor
{
void AddErrors(ObjectValidationContext context);
Task AddErrorsAsync(ObjectValidationContext context);
}
}
}

7
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs

@ -1,20 +1,21 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
namespace Volo.Abp.Validation
{
public interface IObjectValidator
{
void Validate(
Task ValidateAsync(
object validatingObject,
string name = null,
bool allowNull = false
);
List<ValidationResult> GetErrors(
Task<List<ValidationResult>> GetErrorsAsync(
object validatingObject,
string name = null,
bool allowNull = false
);
}
}
}

17
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Reflection;
@ -16,7 +17,7 @@ namespace Volo.Abp.Validation
_objectValidator = objectValidator;
}
public virtual void Validate(MethodInvocationValidationContext context)
public virtual async Task ValidateAsync(MethodInvocationValidationContext context)
{
Check.NotNull(context, nameof(context));
@ -46,7 +47,7 @@ namespace Volo.Abp.Validation
ThrowValidationError(context);
}
AddMethodParameterValidationErrors(context);
await AddMethodParameterValidationErrorsAsync(context);
if (context.Errors.Any())
{
@ -60,7 +61,7 @@ namespace Volo.Abp.Validation
{
return false;
}
if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault<DisableValidationAttribute>(context.Method) != null)
{
return true;
@ -82,22 +83,22 @@ namespace Volo.Abp.Validation
);
}
protected virtual void AddMethodParameterValidationErrors(MethodInvocationValidationContext context)
protected virtual async Task AddMethodParameterValidationErrorsAsync(MethodInvocationValidationContext context)
{
for (var i = 0; i < context.Parameters.Length; i++)
{
AddMethodParameterValidationErrors(context, context.Parameters[i], context.ParameterValues[i]);
await AddMethodParameterValidationErrorsAsync(context, context.Parameters[i], context.ParameterValues[i]);
}
}
protected virtual void AddMethodParameterValidationErrors(IAbpValidationResult context, ParameterInfo parameterInfo, object parameterValue)
protected virtual async Task AddMethodParameterValidationErrorsAsync(IAbpValidationResult context, ParameterInfo parameterInfo, object parameterValue)
{
var allowNulls = parameterInfo.IsOptional ||
parameterInfo.IsOut ||
TypeHelper.IsPrimitiveExtended(parameterInfo.ParameterType, includeEnums: true);
context.Errors.AddRange(
_objectValidator.GetErrors(
await _objectValidator.GetErrorsAsync(
parameterValue,
parameterInfo.Name,
allowNulls
@ -105,4 +106,4 @@ namespace Volo.Abp.Validation
);
}
}
}
}

9
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs

@ -2,6 +2,7 @@ using Microsoft.Extensions.Options;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
@ -18,9 +19,9 @@ namespace Volo.Abp.Validation
Options = options.Value;
}
public virtual void Validate(object validatingObject, string name = null, bool allowNull = false)
public virtual async Task ValidateAsync(object validatingObject, string name = null, bool allowNull = false)
{
var errors = GetErrors(validatingObject, name, allowNull);
var errors = await GetErrorsAsync(validatingObject, name, allowNull);
if (errors.Any())
{
@ -31,7 +32,7 @@ namespace Volo.Abp.Validation
}
}
public virtual List<ValidationResult> GetErrors(object validatingObject, string name = null, bool allowNull = false)
public virtual async Task<List<ValidationResult>> GetErrorsAsync(object validatingObject, string name = null, bool allowNull = false)
{
if (validatingObject == null)
{
@ -58,7 +59,7 @@ namespace Volo.Abp.Validation
{
var contributor = (IObjectValidationContributor)
scope.ServiceProvider.GetRequiredService(contributorType);
contributor.AddErrors(context);
await contributor.AddErrorsAsync(context);
}
}

6
framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs

@ -15,13 +15,13 @@ namespace Volo.Abp.Validation
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
Validate(invocation);
await ValidateAsync(invocation);
await invocation.ProceedAsync();
}
protected virtual void Validate(IAbpMethodInvocation invocation)
protected virtual async Task ValidateAsync(IAbpMethodInvocation invocation)
{
_methodInvocationValidator.Validate(
await _methodInvocationValidator.ValidateAsync(
new MethodInvocationValidationContext(
invocation.TargetObject,
invocation.Method,

27
framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs

@ -39,7 +39,8 @@ namespace Volo.Abp.FluentValidation
},
MyMethodInput3 = new MyMethodInput3
{
MyStringValue3 = "ccc"
MyStringValue3 = "ccc",
MyBoolValue3 = true
}
});
@ -62,12 +63,13 @@ namespace Volo.Abp.FluentValidation
},
MyMethodInput3 = new MyMethodInput3
{
MyStringValue3 = "c"
MyStringValue3 = "c",
MyBoolValue3 = false
}
}
)
);
exception.ValidationErrors.ShouldContain(x => x.MemberNames.Contains("MyStringValue"));
exception.ValidationErrors.ShouldContain(x => x.MemberNames.Contains("MyMethodInput2.MyStringValue2"));
exception.ValidationErrors.ShouldContain(x => x.MemberNames.Contains("MyMethodInput3.MyStringValue3"));
@ -100,7 +102,7 @@ namespace Volo.Abp.FluentValidation
output.ShouldBe("444");
}
[DependsOn(typeof(AbpAutofacModule))]
[DependsOn(typeof(AbpFluentValidationModule))]
public class TestModule : AbpModule
@ -162,6 +164,8 @@ namespace Volo.Abp.FluentValidation
{
public string MyStringValue3 { get; set; }
public bool MyBoolValue3 { get; set; }
}
public class MyMethodInput4
@ -175,7 +179,8 @@ namespace Volo.Abp.FluentValidation
{
RuleFor(x => x.MyStringValue).Equal("aaa");
RuleFor(x => x.MyMethodInput2.MyStringValue2).Equal("bbb");
RuleFor(customer => customer.MyMethodInput3).SetValidator(new MyMethodInput3Validator());
RuleFor(x => x.MyMethodInput3).SetValidator(new MyMethodInput3Validator());
RuleFor(x => x.MyMethodInput3).SetValidator(new MyMethodInput3AsyncValidator());
}
}
@ -194,5 +199,15 @@ namespace Volo.Abp.FluentValidation
RuleFor(x => x.MyStringValue3).Equal("ccc");
}
}
public class MyMethodInput3AsyncValidator : MethodInputBaseValidator
{
public MyMethodInput3AsyncValidator()
{
RuleFor(x => x.MyStringValue3).Equal("ccc");
RuleFor(x => x.MyBoolValue3).MustAsync((myBookValue3, cancellation) => Task.FromResult(myBookValue3));
}
}
}
}
}

Loading…
Cancel
Save