c# - 通过 MVC 集成将上下文传递给 FluentValidation 中的集合验证器

标签 c# asp.net-mvc ninject fluentvalidation

有谁知道在使用 FluentValidation 的 MVC4 集成和 Ninject Validator Factory 集成时如何将一个验证器的上下文传递给集合验证器?

例子:

public class Foo
{
    public IEnumerable<Bar> Bars { get; set; } 
}

public class Bar
{
    public string Bizz { get; set; }
}

public class FooValidator : AbstractValidator<Foo>
{

    public FooValidator()
    {
        // TODO: send context instance (Foo object) to each BarValidator?
        RuleFor(f => f.Bars).SetCollectionValidator(new BarValidator(/* my context instance here */ ));
    }
}

public class BarValidator : AbstractValidator<Bar>
{
    private IEnumerable<Bar> BarList { get; set; }

    public BarValidator(){ /* this is what the validator factory currently uses but i want to use the one that passes the fooInstance some how */ }

    public BarValidator(Foo fooInstance)
    {
        BarList = fooInstance.Bars.Where(b => b != null).ToList();

        // some function here to validate the Bizz property based on other Bar objects in the BarList collection
        RuleFor(f => f.Bizz).NotEmpty()/* .SomeBizzSiblingFunction() */;

    }
}

当我使用这个 Ninject Validator Factory 时

public class NinjectValidatorFactory : ValidatorFactoryBase
{
    /// <summary>
    /// Initializes a new instance of the <see cref="NinjectValidatorFactory"/> class.
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    public NinjectValidatorFactory(IKernel kernel)
    {
        Kernel = kernel;
    }

    /// <summary>
    /// Gets or sets the kernel.
    /// </summary>
    /// <value>The kernel.</value>
    public IKernel Kernel { get; set; }

    /// <summary>
    /// Creates an instance of a validator with the given type using ninject.
    /// </summary>
    /// <param name="validatorType">Type of the validator.</param>
    /// <returns>The newly created validator</returns>
    public override IValidator CreateInstance(Type validatorType)
    {
        if (((IList<IBinding>)Kernel.GetBindings(validatorType)).Count == 0)
        {
            return null;
        }

        return Kernel.Get(validatorType) as IValidator;
    }
}

并将相关的验证器工厂添加到 MVC ModelValidatorProviders 并绑定(bind)它们。

ModelValidatorProviders.Providers.Add(new FluentValidationModelValidatorProvider(new NinjectValidatorFactory(kernel)));

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

AssemblyScanner.FindValidatorsInAssemblyContaining<FooValidator>()
                            .ForEach(match => kernel.Bind(match.InterfaceType).To(match.ValidatorType).InRequestScope());

所以它最终可以在 Controller 中像这样使用,所以我不必每次都新建一个验证器..但我还需要在验证时传递相关的上下文实例。

public class FooController : Controller {
    public ActionResult Create() {
        return View();
    }

    [HttpPost]
    public ActionResult Create(Foo foo) {

        if(! ModelState.IsValid) { // re-render the view when validation failed.
            return View("Create", foo);
        }

        return RedirectToAction("Index");

    }
}

最佳答案

我找到了一种方法。见下文:

public class FooValidator : AbstractValidator<Foo>, IValidatorInterceptor   
{

    public FooValidator() { }

    public ValidationContext BeforeMvcValidation(ControllerContext controllerContext, ValidationContext validationContext)
    {
        RuleFor(f => f.Bar).SetCollectionValidator(new BarValidator(validationContext.InstanceToValidate as Foo));

        return validationContext;
    }

    public ValidationResult AfterMvcValidation(ControllerContext controllerContext, ValidationContext validationContext, ValidationResult result)
    {
        return result;
    }
}

使用验证器拦截器并在 BeforeMvcValidation 方法中而不是在构造函数中应用规则。然后将验证上下文实例传递给 BarValidator。

关于c# - 通过 MVC 集成将上下文传递给 FluentValidation 中的集合验证器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15853991/

相关文章:

asp.net-mvc - 保存 dbml 后,Linq DataContext 类无法在我的 MVC 中访问

asp.net - IIS7中 'classic'和 'integrated'管道模式有什么区别?

c# - 是否有用于设置 HTML 大小属性和 MaxLength 的 MVC5 模型属性?

c# - 负载下的 Ninject WebAPI.SelfHost 性能问题(每隔几秒出现几秒)

c# - 如何将 AutoMapper 与 Ninject.Web.Mvc 一起使用?

c# - 如果输入字符串是二进制/十六进制,如何在 C# 中检查。数字?

C#:检查一组枚举值的最佳方法?

c# - linux/mono 上的 HTTP 性能

c# - 有完整的IEquatable实现引用吗?

c# - 使用 Ninject 工厂方法将 IEnumerable 注入(inject)构造函数