diff --git a/docs/en/Validation.md b/docs/en/Validation.md index c4821adf65..1d24c5e2a6 100644 --- a/docs/en/Validation.md +++ b/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; } } ```` diff --git a/docs/zh-Hans/Validation.md b/docs/zh-Hans/Validation.md index f6b2daf31f..6e46b07aed 100644 --- a/docs/zh-Hans/Validation.md +++ b/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; } } ```` diff --git a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs b/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs index ccc290f354..e2d0f39372 100644 --- a/framework/src/Volo.Abp.FluentValidation/Volo/Abp/FluentValidation/FluentObjectValidationContributor.cs +++ b/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)); diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs index 912f68e4af..15e367cefc 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationObjectValidationContributor.cs +++ b/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 errors, object validatingObject, int currentDepth) diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs index fd413bc498..89eec62116 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IMethodInvocationValidator.cs +++ b/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); } } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs index ca50901bcd..45d0ddcd9b 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidationContributor.cs +++ b/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); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs index 0ce723bab8..1b7c5881ee 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs +++ b/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 GetErrors( + Task> GetErrorsAsync( object validatingObject, string name = null, bool allowNull = false ); } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs index 584f787a6e..3aeaf57fc7 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs +++ b/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(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 ); } } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs index d8e0c60b65..8e13d72938 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs +++ b/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 GetErrors(object validatingObject, string name = null, bool allowNull = false) + public virtual async Task> 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); } } diff --git a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs b/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs index b4ce642471..0a0f4fcf5f 100644 --- a/framework/src/Volo.Abp.Validation/Volo/Abp/Validation/ValidationInterceptor.cs +++ b/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, diff --git a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs b/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs index a93eabda1d..6263d03ddd 100644 --- a/framework/test/Volo.Abp.FluentValidation.Tests/Volo/Abp/FluentValidation/ApplicationService_FluentValidation_Tests.cs +++ b/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)); + } + } } -} \ No newline at end of file +}