Как получить коллекцию ошибок состояния модели в ASP.NET MVC?

145

Как получить коллекцию ошибок в представлении?

Я не хочу использовать Html Helper Validation Summary или Validation Message. Вместо этого я хочу проверить наличие ошибок и, если они есть, отобразить их в определенном формате. Также на элементах управления вводом я хочу проверить наличие ошибки определенного свойства и добавить класс для ввода.

PS Я использую Spark View Engine, но идея должна быть такой же.

Поэтому я решил, что могу сделать что-то вроде ...

<if condition="${ModelState.Errors.Count > 0}">
  DispalyErrorSummary()
</if>

....and also...

<input type="text" value="${Model.Name}" 
       class="?{ModelState.Errors["Name"] != string.empty} error" />

....

Или что-то вроде того.

ОБНОВИТЬ

Мое окончательное решение выглядело так:

<input type="text" value="${ViewData.Model.Name}" 
       class="text error?{!ViewData.ModelState.IsValid && 
                           ViewData.ModelState["Name"].Errors.Count() > 0}" 
       id="Name" name="Name" />

Это только добавляет класс css error, если это свойство имеет ошибку.

Райан Монтгомери
источник
1
Возможный дубликат Как получить все ошибки из ASP.Net MVC modelState?
Майкл

Ответы:

210
<% ViewData.ModelState.IsValid %>

или

<% ViewData.ModelState.Values.Any(x => x.Errors.Count >= 1) %>

и для конкретной собственности ...

<% ViewData.ModelState["Property"].Errors %> // Note this returns a collection
Чад Моран
источник
1
свойство ModelState имеет тип словаря, чтобы получить ошибку для передачи имени ключа ViewData.ModelState ["Name"]
относительно "ViewData.ModelState [" Свойство "]. Ошибки" это вызовет исключение нулевой ссылки, если не было ключа с именем "Свойство"? было бы лучше сначала проверить на null в ViewData.ModelState ["Property"] перед чтением в ошибках?
Дэвид Холлоуэлл - MSFT
@DaveH Да, вы должны сначала полностью проверить существование
Алекс Лайман
61

Чтобы просто получить ошибки от ModelState, используйте этот Linq:

var modelStateErrors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors);
Крис Маккензи
источник
2
это бросило бы исключение нулевой ссылки, если бы не было ключа с указанным именем? было бы лучше сначала проверить на null на ViewData.ModelState [ключ] до чтения в ошибки?
Дэвид Холлоуэлл - MSFT
5
Поскольку мы начинаем с итерации по this.ModelState.Keys, я не вижу возможности для KeyNotFoundException. Я думаю, что проверка будет излишней.
Крис Маккензи
28

Это даст вам одну строку со всеми ошибками с разделением запятой

string validationErrors = string.Join(",",
                    ModelState.Values.Where(E => E.Errors.Count > 0)
                    .SelectMany(E => E.Errors)
                    .Select(E => E.ErrorMessage)
                    .ToArray());
UshaP
источник
Это единственное, что я нашел во всем этом списке, что на самом деле распечатывает ошибки! Спасибо
Джейми
6

Спасибо Чад! Чтобы показать все ошибки, связанные с ключом, вот что я придумал. По какой-то причине базовый помощник Html.ValidationMessage показывает только первую ошибку, связанную с ключом.

    <%= Html.ShowAllErrors(mykey) %>

HtmlHelper:

    public static String ShowAllErrors(this HtmlHelper helper, String key) {
        StringBuilder sb = new StringBuilder();
        if (helper.ViewData.ModelState[key] != null) {
            foreach (var e in helper.ViewData.ModelState[key].Errors) {
                TagBuilder div = new TagBuilder("div");
                div.MergeAttribute("class", "field-validation-error");
                div.SetInnerText(e.ErrorMessage);
                sb.Append(div.ToString());
            }
        }
        return sb.ToString();
    }
Rake36
источник
6

Собрав несколько ответов сверху, вот что я в итоге использовал:

var validationErrors = ModelState.Values.Where(E => E.Errors.Count > 0)
    .SelectMany(E => E.Errors)
    .Select(E => E.ErrorMessage)
    .ToList();

validationErrorsзаканчивается тем, List<string>что содержит каждое сообщение об ошибке. Оттуда легко сделать то, что вы хотите с этим списком.

введите описание изображения здесь

Кейси Крукстон
источник
2

Вот это В.Б.

Dim validationErrors As String = String.Join(",", ModelState.Values.Where(Function(E) E.Errors.Count > 0).SelectMany(Function(E) E.Errors).[Select](Function(E) E.ErrorMessage).ToArray())
MaylorTaylor
источник
0

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

public static String ShowAllErrors<T>(this HtmlHelper helper) {
    StringBuilder sb = new StringBuilder();
    Type myType = typeof(T);
    PropertyInfo[] propInfo = myType.GetProperties();

    foreach (PropertyInfo prop in propInfo) {
        foreach (var e in helper.ViewData.ModelState[prop.Name].Errors) {
            TagBuilder div = new TagBuilder("div");
            div.MergeAttribute("class", "field-validation-error");
            div.SetInnerText(e.ErrorMessage);
            sb.Append(div.ToString());
        }
    }
    return sb.ToString();
}

Где T - это тип вашей "ViewModel".

Gerard
источник