Отключить проверку модели в Asp.Net MVC - PullRequest
8 голосов
/ 26 августа 2010

Как отключить проверку модели для одного действия в контроллере?Или я могу сделать это для каждой модели, зарегистрировав тип модели при запуске где-нибудь?

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

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

Насколько я понимаю, это рекомендуемый подход (не иметь логики в контроллерах), поэтому я нахожу немного странным, что я не могу найти что-то о том, как можно отключить проверку модели (для каждого действия или для типа модели).

Обратите внимание, что я не хочу отключать проверку модели для всего веб-приложения (удаляя провайдеров проверки), и я не хочу отключать проверку ввода, которая проверяет наличие вредоносного кода.


ОБНОВЛЕНИЕ

Я использую .Net 4.0 и MVC 3 Preview 1

Ответы [ 7 ]

11 голосов
/ 05 июня 2012

Просто удалите ненужные элементы, прежде чем проверять, действительна ли модель

ModelState.Remove("Email");
if (ModelState.IsValid)
{
   // your logic
}
10 голосов
/ 20 ноября 2012

Я решил эту проблему с помощью этого кода:

public ActionResult Totals(MyModel model)
{
    ModelState.Clear();
    return View(model);
}

Не уверен, что это правильный путь.

3 голосов
/ 30 августа 2010

К сожалению, кажется, что нет простого способа отключить проверку модели, происходящую в ModelBinder, за исключением регистрации каждого отдельного типа модели, который вы не хотите проверять (включая вложенные сложные типы) с конкретным ModelBinder. Это можно сделать с помощью следующего кода:

ModelBinders.Binders[typeof(MyModelType)] = new NonValidatingModelBinder();

Создание атрибута SkipValidationAttribute, который может быть присоединен к методам действия или параметрам метода действия, представляется невозможным, поскольку его следует реализовать в ControllerActionInvoker, но нет способа сообщить ModelBinder, что он должен выполнить какую-либо проверку в SetProperty. () и методы OnModelUpdated при вызове BindModel () в методе GetParameterValue ().

2 голосов
/ 26 сентября 2010

Мне определенно не нравится это дополнение в версии 2.0, потому что, как вы указали в своем вопросе, проверка имеет больше смысла в слое Service. Таким образом, вы можете повторно использовать его в других не-веб-приложениях и тестировать его проще, не издеваясь над механизмом автоматической проверки.

Проверка на уровне контроллера не имеет смысла, поскольку в этой части вы можете проверять только данные модели, а не бизнес-правила. Например, подумайте о службе, ответственной за добавление новых комментариев, и о пользователе, который хочет опубликовать новый, данные в комментарии, которые он / она публикует, могут быть действительными, но что произойдет, если пользователю запретят комментировать из-за неправильного поведения в прошлом? Вы должны выполнить некоторую проверку на уровне Service, чтобы убедиться, что этого не происходит, и, если это произойдет, выдать исключение. Короче говоря, проверка должна выполняться на уровне службы.

Я использую xVal в качестве моей инфраструктуры валидации, потому что она совместима с DataAnnotationModel, позволяет размещать валидацию там, где я хочу, и выполняет валидацию на стороне клиента без лишних усилий, даже на стороне удаленного клиента. Вот как я использую его в начале каждого из моих сервисов, например, сервис входа в систему:

public void SignIn(Login login) {
    var loginErrors = DataAnnotationsValidationRunner.GetErrors(login);

    // Model validation: Empty fields?
    if (loginErrors.Any())
        throw new RulesException(loginErrors);

    // Business validation: Does the user exist? Is the password correct?
    var user = this._userRepository.GetUserByEmail(login.Email);

    if (user == null || user.Password != login.Password)

        throw new RulesException(null, "Username or password invalids");

    // Other login stuff...
}

Простой, независимый от сети и легкий ... затем в контроллере:

public RedirectResult Login(Login login) {

    // Login the user

    try {

        this._authenticationRepository.SignIn(login);

    } catch (RulesException e) {

        e.AddModelStateErrors(base.ModelState, "Login");

    }

    // Redirect

    if (base.ModelState.IsValid)
        return base.Redirect(base.Url.Action("Home"));
    else return base.Redirect(base.Url.Action("Login"));
}
2 голосов
/ 27 августа 2010

Я бы порекомендовал вам выполнить проверку в обоих местах, а не пытаться отключить проверку в пользовательском интерфейсе.Я понимаю вашу точку зрения, что служба не может предполагать, что ей передаются действительные данные - это действительная проблема и причина, по которой ваша служба должна пройти проверку.Но вы должны также иметь подтверждение в вашем пользовательском интерфейсе.Это также хорошо, потому что у вас может быть проверка на стороне клиента, чтобы предотвратить ошибки пользователя и дать вам лучший опыт.

1 голос
/ 21 октября 2016

Я знаю, что на этот вопрос уже был дан ответ, но вам действительно нужно было расширить DataAnnotationsValidatorProvider и переопределить метод GetValidators.

Затем при запуске вы удалили DataAnnotationsValidatorProvider из ModelValidatorProviders.Providers и добавьте новый.

Само собой разумеется, если вы просто не хотите никакой проверки, вы можете просто использовать метод GetValidators, возвращающий пустую коллекцию.

В моем случае мне нужно удалить проверку только при отправке форм, сохраняя при этом проверку на стороне клиента, следовательно, следующее:

public class DynamicModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
   GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
    {
        if (context.HttpContext.Request.HttpMethod == "POST")
        {
            return new ModelValidator[] { };
        }

        return base.GetValidators(metadata, context, attributes);
    }
}
0 голосов
/ 27 августа 2010

использую [ValidateInput (false)]

Не уверен, мешает ли это проверке модели или только IIS отправляет проверку.

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