Выборочная проверка дочерних свойств - Свободная проверка в MVC - PullRequest
3 голосов
/ 24 января 2012

Я использую Fluent Validation с библиотекой Ninject.Web.Mvc.FluentValidation, чтобы автоматически подключать все мои валидаторы (и использую внедрение зависимостей для создания валидаторов).

Я создал следующие модели:

public class Parent
{
    public string Name { get; set; }

    public Child Child1 { get; set; }
    public Child Child2 { get; set; }
}

public class Child
{
    public string ChildProperty { get; set; }
}

Со следующими валидаторами:

public class ParentValidator : AbstractValidator<Parent>
{
    public ParentValidator()
    {
         RuleFor(model => model.Name).NotEmpty();
         RuleFor(model => model.Child1).SetValidator(new ChildValidator());
    }
}

public class ChildValidator : AbstractValidator<Child>
{
    public ChildValidator()
    {
        RuleFor(model => model.ChildProperty).NotEmpty();
    }
}

Мои просмотры:

@model Parent

@using(Html.BeginForm())
{
    @Html.EditorFor(model => model.Name)
    @Html.ValidationMessageFor(model => model.Name)

    @Html.EditorFor(model => model.Child1)
    @Html.EditorFor(model => model.Child2)

    <input type="submit" value="Save" />
}

@model Child

@Html.EditorFor(model => model.ChildProperty)
@Html.EditorFor(model => model.ChildProperty)

Я пытаюсь создать родительскую модель с двумядочерние свойства.Свойство Child1 обязательно, но свойство Child2 необязательно.Это нормально работает при нормальных обстоятельствах, но когда я использую модуль Ninject для автоматического подключения валидаторов, то он обнаруживает, что существует класс валидатора для класса Child, и связывает все свойства Child в Parent.

Можно ли как-то предотвратить это, не избавившись от модуля Ninject?

Ответы [ 3 ]

2 голосов
/ 20 февраля 2012

Поскольку автоматическое соединение не может условно понять, когда применять класс ChildValidator во время привязки модели, похоже, у вас есть несколько альтернатив:

  1. Решите, еслиочень важно повторное использование моделей дочерних представлений. Столкнувшись с такой ситуацией, я бы, вероятно, свернул дочерние элементы в родительский для этого представления, если бы дочерние объекты не были очень сложными и было не более пары представлений.которые использовали дочерние объекты отдельно.Я всегда неохотно чувствую себя супер-СУХОЙ с моделями представлений, поскольку в моем опыте структуры страниц со временем расходятся.
  2. Устранение ошибок ModelState для Child2. Отсюда вы можете полностью контролировать валидацию для Child2, включая отдельный валидатор для Child2 в этом уникальном контексте и применять его вручную.Это одна из причин, по которой мне нравится FluentValidation - возможность применять разную логику проверки к одной и той же модели представления в разных контекстах, в отличие от аннотаций данных.

Значение автоматической регистрации (т. Е. Вседополнительный код, который он исключает) исключил бы возможность его отключения для этого одного случая, IMO.

0 голосов
/ 04 июля 2014

Если вы не хотите автоматически связывать дочерние валидаторы, вы можете добавить пустой интерфейс к дочернему валидатору:

открытый класс PersonalDataValidator: AbstractValidator, IChildValidator

А затем на вашем заводе:

public class FluentValidatorFactory : ValidatorFactoryBase
{
    private readonly IKernel _kernel;

    public FluentValidatorFactory(IKernel kernel)
    {
        _kernel = kernel;
    }

    public override IValidator CreateInstance(Type validatorType)
    {
        IValidator validator = _kernel.Resolve(validatorType) as IValidator;

        ////we dont want that windosr auto wires up all child validators. 
        var childValidator = validator as IChildValidator;

        if (childValidator == null)
        {
            return validator;
        }

            return null;
    }
}
0 голосов
/ 23 февраля 2012

Вы забыли установить валидатор для второго дочернего свойства:

public class ParentValidator : AbstractValidator<Parent>
{
    public ParentValidator()
    {
         RuleFor(model => model.Name).NotEmpty();
         RuleFor(model => model.Child1).SetValidator(new ChildValidator());
         RuleFor(model => model.Child2).SetValidator(new ChildValidator());
    }
}
...