does anyone know how I could pass a context for one validator to a collection validator while using the MVC4 integration of FluentValidation and the Ninject Validator Factory integration?
Example:
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() */;
}
}
when I am using this 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;
}
}
and adding the relevant validator factory to the MVC ModelValidatorProviders and binding them.
ModelValidatorProviders.Providers.Add(new FluentValidationModelValidatorProvider(new NinjectValidatorFactory(kernel)));
DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;
AssemblyScanner.FindValidatorsInAssemblyContaining<FooValidator>()
.ForEach(match => kernel.Bind(match.InterfaceType).To(match.ValidatorType).InRequestScope());
so it eventually can be used like this in the controller, so I don't have to new up a validator each time.. but I need to also pass the relevant context instance at the time of validating.
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");
}
}