Fluent验证规则,子集和嵌套

Alw*_*wyn 2 c# validation asp.net-mvc fluentvalidation

给出一个看起来像这样的验证器类

 public class SomeValidator : AbstractValidator<SomeObject>
 {
      public SomeValidator(){
           RuleSet("First",
                () => {
                     RuleFor(so => so.SomeMember).SetValidator(new SomeMemberValidator())
           });
           RuleSet("Second",
                () => ... Code Does Not Matter ... );
           RuleSet("Third",
                () => ... Code Does Not Matter ... );
      }
 }
Run Code Online (Sandbox Code Playgroud)

另一个做内部成员验证

 public class SomeMemberValidator: AbstractValidator<SomeMember>
 {
      public SomeValidator(){
           RuleSet("Fourth",
                () => {
                     ... Code Does Not Matter ...
           });
      }
 }
Run Code Online (Sandbox Code Playgroud)

问题是,我想运行特定的规则集:"First","Second"和"Fourth".我不希望"第三"运行.

鉴于Validate方法签名只接受一个规则集参数,我没有看到任何方法来执行此操作.有"*",但我不想运行所有规则.

请帮忙.

knr*_*knr 6

您可以使用验证器构造函数而不是RuleSet作为此问题的解决方法.只需在验证器类中创建枚举,然后在创建验证器时使用其值.

我这样会根据构造函数中设置的模式激活正确的规则.

public class UserValidator : AbstractValidator<User>
{
    public enum Mode
    {
        Create,
        Edit
    }

    public UserValidator()
    {
        // Default rules...
    }

    public UserValidator(UserValidator.Mode mode)
        : this()
    {
        if (mode == Mode.Edit)
        {
            // Rules for Edit...

            RuleFor(so => so.SomeMember)
                .SetValidator(
                    new SomeMemberValidator(SomeMemberValidator.Mode.SomeMode))
        }

        if (mode == Mode.Create)
        {
            // Rules for Create...

            RuleFor(so => so.SomeMember)
                .SetValidator(
                    new SomeMemberValidator())
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为它实际上比使用RuleSet更灵活.

关于FluentValidation MVC集成只有一个小问题: User类不能具有属性,[Validator(typeof(UserValidator))]因为然后将使用默认构造函数创建UserValidator,然后才能在控制器方法中执行任何操作.

必须手动创建和调用Validator.像那样的例子:

public class UserController : Controller
{
    [HttpPost]
    public ActionResult Create(User userData)
    {
        var validator = new UserValidator(UserValidator.Mode.Create);

        if (ValidateWrapper(validator, userData, this.ModelState))
        {
            // Put userData in database...
        }
        else
        {
            // ValidateWrapper added errors from UserValidator to ModelState.
            return View();
        }
    }

    private static bool ValidateWrapper<T>(FluentValidation.AbstractValidator<T> validator, T data, ModelStateDictionary modelState)
    {
        var validationResult = validator.Validate(data);

        if (!validationResult.IsValid)
        {
            foreach (var error in validationResult.Errors)
                modelState.AddModelError(error.PropertyName, error.ErrorMessage);

            return false;
        }

        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)


goe*_*ing 5

您可以执行多个RuleSet,但我认为您不能执行内部RuleSet.

validator.Validate(new ValidationContext<SomeObject>(person, new PropertyChain(), new RulesetValidatorSelector("First", "Second", "Fourth")));
Run Code Online (Sandbox Code Playgroud)

资源

另一个选择是调查源代码并尝试思考一种方法.ValidationContext的第三个参数是一个接口IValidatorSelector,也许你可以通过自定义类运气.