MVC3 Удалить ошибки ModelState

84

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

Мне удалось отключить проверку на стороне клиента, дав моей кнопке отправки «Загрузить изображение» значение класса «отмена имени-стиля», поэтому

<input type="submit" name="UploadImageButton" value="Upload Image" class="style-name cancel" /> 

Теперь, когда я отправляю ответ, у моей модели есть свойство UploadImageButton, при нажатии этой кнопки оно заполняет это свойство (имя ввода соответствует свойству). Таким образом, я знаю, была ли форма отправлена ​​моей настоящей кнопкой «Отправить» или кнопкой UploadImageButton.

У меня такой вопрос ... Как отключить проверку ServerSide? Я не хочу, чтобы сводная информация о проверке отображалась, когда пользователь нажимает эту кнопку. Я знаю, что вы можете добавлять ошибки пользовательской модели с помощью этого

ModelState.AddModelError("{key}", "{error msg}");

Я ищу средство для удаления ошибок модели. Это возможно?

РЕДАКТИРОВАТЬ:

Вот что я придумал:

foreach (var key in ModelState.Keys.ToList().Where(key => ModelState.ContainsKey(key))) {
     //ModelState.Remove(key); //This was my solution before
     ModelState[key].Errors.Clear(); //This is my new solution. Thanks bbak
}
Джефф Редди
источник
Зачем ты делаешь Where(key => ModelState.Keys.Contains(key))? Кажется, что предложение Where является избыточным, потому что каждый ключ в ModelState.Keys будет иметь его ModelState.Keys.Contains (key) return true.
Максим Заславский
1
Я обновил вопрос и текст, чтобы использовать более короткий метод в ModelState.ContainsKey, хотя вы ошиблись в своем предположении. Они делают то же самое.
Джефф Редди
Извините, возможно, я неправильно объяснил или неправильно понял ваш ответ. Вы правы ModelState.ContainsKey(key)и ModelState.Contains(key)делаете то же самое, но я хочу сказать, что все значения в ModelState.Keys.ToList()will по своей природе содержатся в ModelState, поэтому все Whereпредложение является избыточным и снижает производительность. Хотя мелочь.
Максим Заславский
ReSharper собрал все вместе. Спасибо что подметил это.
Джефф Редди
1
Просто обратите внимание на способ узнать, какая кнопка была источником отправки. В ViewModel вам не обязательно иметь это свойство. Просто добавьте параметр FormCollection в контроллер: public ActionResult Index (модель YourViewModelClass, FormCollection formCollection). И проверьте, есть ли в нем название кнопки: if (formCollection ["UploadImageButton"]! = Null). Я думаю, будет лучше, если у вас будет больше кнопок отправки.
jannagy02

Ответы:

146

Вы можете удалить ошибки модели, сделав что-то вроде этого:

if (ModelState.ContainsKey("{key}"))
    ModelState["{key}"].Errors.Clear();
bbak
источник
1
Это именно то, что я искал. Я изменил свой выбранный ответ (извините, Адам Тюлипер).
Джефф Редди
Спасибо, это сэкономило мне пару часов!
Agent007
1
На всякий случай, если кому-то было интересно, это также влияетModelState.IsValid
Red Taz
2
как ни странно, в моем случае этого было недостаточно. Мне пришлось добавить ModelState ["{ключ}"]. ValidationState = ModelValidationState.Valid;
AGuyCalledGerald
67

Это основано на предыдущих ответах, но немного упрощает их:

foreach (var modelValue in ModelState.Values)
{
    modelValue.Errors.Clear();
}
Дэн Фридман
источник
7

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

В вашем случае у вас есть несколько кнопок отправки для одной и той же формы, но вы действительно не отправляете форму, когда загружаете изображение. Чтобы предотвратить проверку на стороне клиента, вы можете использовать класс «cancel», как вы уже указали, но я также рекомендую иметь вторую кнопку отправки в другой форме, и в этом случае она не вызывает проверки в вашей основной форме.

Есть второе преимущество использования другой формы: вы можете отправить ее другому методу ActionResult, который будет обрабатывать логику загрузки изображения. Этот другой метод просто не потрудился бы проверить свойство IsValid состояния модели: он заботится только о том, есть ли информация в изображении, и это можно проверить отдельно. (Даже если вы используете тот же метод ActionResult, вы можете направить логику так, чтобы не полагаться на свойство IsValid состояния модели.)

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

foreach (var key in ModelState.Keys)
{
    ModelState[key].Errors.Clear();
}

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

Последнее, что нужно проверить в этих случаях, - это то, есть ли у вас значения, которые только иногда присутствуют в представлении, что не вызовет проверки на стороне клиента (их нет в представлении), но действительно приведет к проблемам проверки на стороне сервера. В этом случае лучше всего использовать @ Html.HiddenFor (model => model.PropertyName, если вы можете, предполагая, что значение уже установлено, оно просто не отображается в этом представлении.

Джеймс
источник
7

Я иногда его использую, поэтому сделал из него метод расширения:

public static ModelStateDictionary ClearError(this ModelStateDictionary m, string fieldName)
{
    if (m.ContainsKey(fieldName))
        m[fieldName].Errors.Clear();
    return m;
}

Его можно использовать для удаления ошибок в нескольких полях.

Mahmoodvcs
источник
3

используйте ModelState.Remove ("{key}"), чтобы удалить ошибку из модели, что приведет к сбросу ModelState.IsValid в значение true

ModelState.Remove("{key}");
Ибрар
источник