【问题标题】:How to await method in PropertyValidator's overridden IsValid?如何在 PropertyValidator 的重写 IsValid 中等待方法?
【发布时间】:2020-03-26 16:17:12
【问题描述】:

我正在尝试在 PropertyValidator 类中使用我的数据存储库。问题是存储库中的方法是异步的......我看不到IsValidAsync 可以覆盖。

using System.Collections.Generic;
using System.Threading.Tasks;
using FluentValidation.Validators;
using AccountApi.Domain.Repositories;

namespace AccountApi.Domain.Validators
{
    public class UserInputValidator<TElement> : PropertyValidator
    {
        private IUserRepository _userRepository;

        public UserInputValidator(IUserRepository userRepository)
            : base("{Message}.")
        {
            _userRepository = userRepository;
        }

        protected override bool IsValid(PropertyValidatorContext context)
        {
            var id = (int)context.PropertyValue;
            var user = await _userRepository.GetById(id); // <--- HERE is the problem  

            // ..... 

            return true;
        }
    }
} 

我试着改成这样:

protected override async Task<bool> IsValidAsync(PropertyValidatorContext context)   

...但它也不起作用。没有要覆盖的 IsValidAsync

是否可以在 PropertyValidator 中使用async 方法?

【问题讨论】:

    标签: c# asp.net-core .net-core async-await fluentvalidation


    【解决方案1】:

    你走在了正确的轨道上。

    是的,你确实重载了 PropertyValidator 方法 protected virtual async Task&lt;bool&gt; IsValidAsync(PropertyValidatorContext context, CancellationToken cancellation)

    但是你需要使用validator.ValidateAsync(objectToValidate)方法来使用它。

    如果您的验证器包含异步验证器或异步 条件,重要的是你总是在你的 验证器并且从不验证。如果您调用 Validate,那么您的 异步规则会同步运行,这是不可取的。

    Source

    另外参考以下issue Jeremy 建议的地方:

    • 还重载了ShouldValidateAsync方法; 或者更好
    • 使用 AsyncValidatorBase 而不是 PropertyValidator 为您处理 ShouldValidateAsync 重载

    如果您想查看异步属性验证器的working solution,请参阅以下内容。

    【讨论】:

      【解决方案2】:

      是否可以在 PropertyValidator 中使用异步方法?

      您可以在 vs 中按 PropertyValidator 上的 F12 以查看其方法。

      public abstract class PropertyValidator : IPropertyValidator
      {
          protected PropertyValidator(IStringSource errorMessageSource);
          protected PropertyValidator(string errorMessage);
          [Obsolete("This constructor will be removed in FluentValidation 9.0. Use the overload that takes an IStringSource instead, passing in a LazyStringSource: PropertyValidator(new LazyStringSource(ctx => MyResourceClass.MyResourceName))")]
          protected PropertyValidator(string errorMessageResourceName, Type errorMessageResourceType);
      
          public PropertyValidatorOptions Options { get; }
      
          public virtual bool ShouldValidateAsync(ValidationContext context);
          public virtual IEnumerable<ValidationFailure> Validate(PropertyValidatorContext context);
          [AsyncStateMachine(typeof(<ValidateAsync>d__7))]
          public virtual Task<IEnumerable<ValidationFailure>> ValidateAsync(PropertyValidatorContext context, CancellationToken cancellation);
          //
          // Summary:
          //     Creates an error validation result for this validator.
          //
          // Parameters:
          //   context:
          //     The validator context
          //
          // Returns:
          //     Returns an error validation result.
          protected virtual ValidationFailure CreateValidationError(PropertyValidatorContext context);
          protected abstract bool IsValid(PropertyValidatorContext context);
          [AsyncStateMachine(typeof(<IsValidAsync>d__10))]
          protected virtual Task<bool> IsValidAsync(PropertyValidatorContext context, CancellationToken cancellation);
          //
          // Summary:
          //     Prepares the FluentValidation.Internal.MessageFormatter of context for an upcoming
          //     FluentValidation.Results.ValidationFailure.
          //
          // Parameters:
          //   context:
          //     The validator context
          protected virtual void PrepareMessageFormatterForValidationError(PropertyValidatorContext context);
      }
      

      所以,尝试使用

      protected override async Task<bool> IsValidAsync(PropertyValidatorContext context, CancellationToken cancellation)
      

      【讨论】:

        【解决方案3】:

        这很简单。只需使用“AsyncPropertyValidator”或“AsyncPropertyValidator

        在你的情况下,它会像

        using System.Collections.Generic;
        using System.Threading.Tasks;
        using FluentValidation.Validators;
        using AccountApi.Domain.Repositories;
            
        namespace AccountApi.Domain.Validators
        {
            public class UserInputValidator<TElement> : AsyncPropertyValidator
            {
                private IUserRepository _userRepository;
        
                public UserInputValidator(IUserRepository userRepository)
                    : base("{Message}.")
                {
                    _userRepository = userRepository;
                }
        
                 public override async Task<bool> IsValidAsync(PropertyValidatorContext context)
                {
                    var id = (int)context.PropertyValue;
                    var user = await _userRepository.GetById(id);
        
                    // .. 
        
                    return true;
                }
            }
        } 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-01-05
          • 2017-10-08
          相关资源
          最近更新 更多