#asp.net-mvc #asp.net-mvc-3
#asp.net-mvc #asp.net-mvc-3
Вопрос:
У меня есть класс, который реализует IValidateObject. Мое бизнес-правило выполняется после того, как я выполняю некоторую дополнительную работу в действии контроллера. Проблема, с которой я сталкиваюсь, заключается в ModelState.Значение isValid по-прежнему равно false. Я пытаюсь найти, как его сбросить или перезапустить, чтобы ModelState был обновлен. Я попробовал TryUpdateModel, который запустил метод Validate, и если я пройду через мое правило, оно теперь будет действительным, но ModelState.Значение isValid по-прежнему равно false (и я вижу, что оно все еще жалуется на то же правило).
[HttpPost]
public ActionResult Create(MyModel model)
{
//ModelState.IsValid is False at this point
//model.Do More Stuff To Satisfy IValidateObject rule. At this point all my rules are valid
TryUpdateModel(model); // <-- If run TryUpdateModel and step through, I can see my rule is valid
if (ModelState.IsValid) // this is still False
{
//Save
}
}
Обновить:
В итоге я вызвал
ModelState.Clear();
[HttpPost]
public ActionResult Create(MyModel model)
{
//model.Do More Stuff To Satisfy IValidateObject rule. At this point all my rules are valid
ModelState.Clear();
TryUpdateModel(model);
if (ModelState.IsValid)
{
//Save
}
}
Ответ №1:
Я не вижу в этом смысла. У вас есть действие контроллера, которое получает пользовательский ввод, который вы вручную исправляете, если он недействителен, и хотите впоследствии проверить, является ли модель действительной или нет. Если вы исправили это вручную, почему вы тестируете еще раз? Вы знаете, что это будет допустимо, не так ли? Какой смысл писать правило проверки, которое вы переопределяете?
Также обратите внимание, что все, что вы исправляете под рукой в действии POST controller (например, обновление свойства модели), должно сопровождаться ModelState.Remove("TheKeyOfThePropertyYouHaveManuallyUpdated")
, чтобы эти изменения вручную имели некоторый эффект.
Комментарии:
1. Я не исправляю введенные данные вручную. Я добавляю дополнительные данные, которые делают мой объект действительным.
2. @Bz, то, что ты делаешь, противоречит передовой практике. Вы должны использовать модели представлений и слой сопоставления, который будет отображать между моделью представления, полученной пользователем, и соответствующей моделью, которую вы передадите на уровень сервиса. Таким образом, ваше действие контроллера должно принимать view model в качестве входного параметра, и после того, как вы убедитесь, что ModelState является допустимым, это означает, что первый уровень проверки пройден (такие вещи, как обязательные поля, форматы, …). Затем вы сопоставляете свою бизнес-модель и переходите на уровень сервиса. Это сервисный уровень, который сообщает о любых бизнес-ошибках в модели.
3. Например, у моего объекта есть дочерняя коллекция. Мое бизнес-правило гласит, что в этой дочерней коллекции должен быть хотя бы один элемент. Однако это не вводится пользователем… конкретный бизнес-домен несколько сложно объяснить. Если вам нужна дополнительная информация, я подумаю о более простом сценарии…
4. @Bz, как я сказал в своем ответе, вы могли бы очистить свойства в ModelState с помощью
ModelState.Remove
. Как только вы удалите соответствующее свойство из состояния модели, оно также удалит соответствующие ошибки. Но если вы это сделаете, я хочу подчеркнуть, что это является нарушением любой надлежащей практики, и вы делаете это на свой страх и риск. Я настаиваю: это не то, что я рекомендую.5. @ Bz, не использовать модели просмотра ужасно. Поверьте мне. Я просто настаиваю, чтобы другие люди, читающие это, были хорошо осведомлены. Если вы используете view models, вам не нужно ничего перезапускать. Приложение будет следовать своему естественному потоку. То, что вы пытаетесь сделать сейчас, борется с тем, каким должен быть MVC.