ASP.NET MVC 3: проверка модели, когда требуется внешняя для модели информация - PullRequest
11 голосов
/ 12 октября 2011

Какой хороший способ проверки модели, когда для ее проверки требуется информация, внешняя по отношению к модели? Например, рассмотрим следующую модель:

public class Rating {
    public string Comment { get; set; }
    public int RatingLevel { get; set; }
}

Системный администратор может затем установить RatingLevels, для которого требуется комментарий. Эти настройки доступны через сервис настроек.

Итак, для полной проверки модели мне нужна внешняя информация, в данном случае служба настройки.

До сих пор я рассмотрел следующее:

  1. Добавление службы в модель. DefaultModelBinder использует System.Activator для создания объекта, чтобы он не проходил через обычный преобразователь зависимостей и Я не могу внедрить сервис в модель, не создав новый механизм связывания моделей (кроме того, это не похоже на правильный путь решения этой проблемы).
  2. Добавьте сервис в аннотацию. Я еще не уверен, что это возможно, но скоро мы продолжим расследование. Это все еще кажется неуклюжим.
  3. Использовать пользовательское связующее для модели . По-видимому, я могу реализовать OnPropertyValidating для проверки пользовательских свойств. Это кажется наиболее предпочтительным, хотя я пока не уверен, как это сделать.

Какой метод, описанный выше или нет, лучше всего подходит для этого типа проблемы проверки?

Ответы [ 4 ]

14 голосов
/ 20 октября 2011

Вариант 1 не подходит. Единственный способ, которым он будет работать, заключается в получении зависимости через анти-шаблон локатора службы.

Опция 2 не работает . Хотя я не мог понять, как это было возможно из-за требований к атрибуту C #, это возможно. См. Следующие ссылки:

Вариант 3: Я не знал об этом ранее, но, как представляется, очень мощный способ написания валидаторов - это использование ModelValidator класса и соответствующего ModelValidatorProvider .

Сначала вы создаете свой собственный ModelValidatorProvider:

public class CustomModelValidatorProvider : ModelValidatorProvider
{
    public CustomModelValidatorProvider(/* Your dependencies */) {}

    public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context)
    {
        if (metadata.ModelType == typeof(YourModel))
        {
            yield return new YourModelValidator(...);
        }
    }
}

ASP.NET MVC IDependencyResolver будет пытаться разрешить вышеуказанного провайдера, поэтому, пока он зарегистрирован в вашем контейнере IoC, вам больше ничего не нужно делать. И тогда ModelValidator:

public class EntryRatingViewModelValidatorMvcAdapter : ModelValidator
{
    public EntryRatingViewModelValidatorMvcAdapter(
            ModelMetadata argMetadata,
            ControllerContext argContext)
                : base(argMetadata, argContext)
    {
        _validator = validator;
    }


    public override IEnumerable<ModelValidationResult> Validate(object container)
    {
        if (/* error condition */)
        {
            yield return new ModelValidationResult
              {
                MemberName = "Model.Member",
                Message = "Rating is required."
              };
        }
    }
}

Поскольку провайдер извлекается через IDependencyResolver, и провайдер имеет полный контроль над возвращенными ModelValidator s, я легко смог ввести зависимости и выполнить необходимую проверку.

5 голосов
/ 13 октября 2011

Вы можете попробовать свободная проверка . Он поддерживает asp.net mvc и DI, поэтому вы можете внедрить внешние службы в ваши валидаторы.

1 голос
/ 12 октября 2011

Предполагая, что вы хотите как клиентскую, так и серверную проверку модели на основе значений, возвращаемых службой, я бы выбрал 2., Добавление службы в аннотацию .

Я даю пример кода в своем ответе на этот вопрос о добавлении валидаторов в модель .Единственным дополнительным шагом в вашем случае является то, что вам нужно будет внедрить ваш сервис в ваш класс, наследуя от DataAnnotationsModelValidatorProvider.

0 голосов
/ 13 октября 2011

Как насчет простого использования IValidateableObject и в этом методе определения правильности валидации или установки ошибок там?

Как использовать IValidatableObject?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...