Как получить все ошибки из ASP.Net MVC modelState?

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

Как я могу это сделать?

30.08.2009 02:41:54
Если вы просто отображаете ошибки, то @Html.ValidationSummary()это быстрый способ отобразить их все как бритва.
levininja 20.01.2014 20:23:09
foreach (var error in ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors)) { DoSomething(error); }
Razvan Dumitru 17.10.2014 13:41:32
15 ОТВЕТОВ
РЕШЕНИЕ
foreach (ModelState modelState in ViewData.ModelState.Values) {
    foreach (ModelError error in modelState.Errors) {
        DoSomethingWith(error);
    }
}

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

521
23.05.2017 11:47:31
Очень полезно. Обратите внимание, что в некоторых сценариях, таких как ошибки привязки и неправильные запросы, будут записи ModelState с пустой строкой для Value.ErrorMessageи вместо этогоValue.Exception.Message
AaronLS 16.09.2014 01:12:30
Ошибки хороши, но иногда вам также нужен ключ состояния модели (то есть имя поля). вы можете получить , что, изменив первую строку на это: foreach (KeyValuePair<string, ModelState> kvp in htmlHelper.ViewData.ModelState) {и вставить эту строку под ним: var modelState = kvp.Value;. Вы можете получить ключ отkvp.Key
viggity 11.04.2018 19:07:21

Используя LINQ :

IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);
523
4.02.2017 07:33:27
Модифицировано для возврата IEnumerable <string> только с сообщением об ошибке :: var allErrors = ModelState.Values.SelectMany (v => v.Errors.Select (b => b.ErrorMessage));
Kieran 19.02.2014 00:30:05
Это здорово, но, к сожалению, окна Watch / Immediate не поддерживают лямбда-
AaronLS 31.03.2014 23:02:07
Да! Мне (вам, кому угодно) нужно "использовать System.Linq;" На вершине. В противном случае вы получили сообщение «Значения не содержат определения для выбора многих». Это отсутствовало в моем случае.
Estevez 19.11.2014 15:30:32
зачем в аду использование вар ?????? не могли бы вы написать `IEnumerable <ModelError> 'вместо этого ???
Hakan Fıstık 1.06.2016 10:20:35
@ hakam-fostok @ jb06 вы оба правы. Печатание List<string> errors = new List<string>()вместо того, чтобы var errors = new List<string>()действительно тратить время, но письмо IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);, где тип возвращаемого значения не совсем понятен, действительно лучше с точки зрения читабельности. (даже если Visual Studio может дать его вам при наведении мыши)
aprovent 18.07.2016 15:46:48

Основываясь на версии LINQ, если вы хотите объединить все сообщения об ошибках в одну строку:

string messages = string.Join("; ", ModelState.Values
                                        .SelectMany(x => x.Errors)
                                        .Select(x => x.ErrorMessage));
190
11.08.2014 09:44:50
Другой вариант заключается в следующем: ModelState.Values.SelectMany (x => x.Errors) .Select (x => x.ErrorMessage) .JoinString (";");
Tod Thomson 15.02.2013 02:06:27
@Tod, IEnumerable.JoinString () ваш собственный метод расширения? См. Stackoverflow.com/q/4382034/188926
Dunc 15.02.2013 09:32:06
Эй, Дунк - да, я подозреваю, что я добавил этот метод расширения в свою базу кода и забыл об этом, а затем подумал, что это метод фреймворка LOL :(
Tod Thomson 17.02.2013 04:55:13
или ... ModelState.Values.SelectMany (O => O.Errors) .Select (O => O.ErrorMessage) .Aggregate ((U, V) => U + "," + V)
fordareh 14.08.2013 00:35:22
Это прекрасно работает, когда вы используете веб-API и возвращаете результат IHttpActionResult. Итак, вы можете просто сделать: return BadRequest (messages); Спасибо, Дунк!
Rich Ward 24.08.2016 15:21:39

И это тоже работает:

var query = from state in ModelState.Values
    from error in state.Errors
    select error.ErrorMessage;
var errors = query.ToArray(); // ToList() and so on...
4
31.07.2012 00:36:50
@Yasser Ты видел ответ Тото?
The Muffin Man 19.03.2014 03:08:29
@ TheMuffinMan да, у меня есть. Что насчет этого ?
Yasser Shaikh 19.03.2014 06:30:23
@Yasser Это лучший ответ. В этом нет ничего плохого, но нет смысла использовать его, когда SelectManyон доступен.
The Muffin Man 19.03.2014 14:44:49

Кроме того, ModelState.Values.ErrorMessageможет быть пустым, но ModelState.Values.Exception.Messageможет указывать на ошибку.

3
5.03.2014 15:04:47

Я смог сделать это с помощью небольшого LINQ,

public static List<string> GetErrorListFromModelState
                                              (ModelStateDictionary modelState)
{
      var query = from state in modelState.Values
                  from error in state.Errors
                  select error.ErrorMessage;

      var errorList = query.ToList();
      return errorList;
}

Вышеуказанный метод возвращает список ошибок проверки.

Дальнейшее чтение :

Как прочитать все ошибки из ModelState в ASP.NET MVC

32
4.03.2019 14:56:25

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

<table class="model-state">
    @foreach (var item in ViewContext.ViewData.ModelState) 
    {
        if (item.Value.Errors.Any())
        { 
        <tr>
            <td><b>@item.Key</b></td>
            <td>@((item.Value == null || item.Value.Value == null) ? "<null>" : item.Value.Value.RawValue)</td>
            <td>@(string.Join("; ", item.Value.Errors.Select(x => x.ErrorMessage)))</td>
        </tr>
        }
    }
</table>

<style>
    table.model-state
    {
        border-color: #600;
        border-width: 0 0 1px 1px;
        border-style: solid;
        border-collapse: collapse;
        font-size: .8em;
        font-family: arial;
    }

    table.model-state td
    {
        border-color: #600;
        border-width: 1px 1px 0 0;
        border-style: solid;
        margin: 0;
        padding: .25em .75em;
        background-color: #FFC;
    }
 </style>
17
21.11.2013 17:38:00
если есть какие-либо крайние случаи, когда это не удается, просто отредактируйте ответ, чтобы исправить это
Simon_Weaver 15.12.2012 02:42:40

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

String messages = String.Join(Environment.NewLine, ModelState.Values.SelectMany(v => v.Errors)
                                                           .Select( v => v.ErrorMessage + " " + v.Exception));

или как метод расширения

public static IEnumerable<String> GetErrors(this ModelStateDictionary modelState)
{
      return modelState.Values.SelectMany(v => v.Errors)
                              .Select( v => v.ErrorMessage + " " + v.Exception).ToList();

}
12
16.01.2013 16:24:00
зачем вам строка со всеми ошибками? не имеет смысла, когда вы хотите что-то сделать с этим в представлении, массив списков намного лучше imho
Daniël Tulp 22.10.2013 08:07:02
Отлаживать. Моей первой проблемой было выяснить, что не так с моим приложением. Я не пытался сказать пользователю просто узнать, что происходит не так. Кроме того, тривиально преобразовать этот пример из создания перечисления строк в перечисление чего-то другого, например, сообщения об ошибке и исключения, так что действительно полезно знать, что вам нужны оба бита информации
Alan Macdonald 22.10.2013 17:40:55
Кстати, вы понимали, что второй метод расширения возвращает IEnumerable <String>, а не просто большую строку?
Alan Macdonald 22.10.2013 17:52:54

Полезно для передачи массива сообщений об ошибках в View, возможно, через Json:

messageArray = this.ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors, (modelState, error) => error.ErrorMessage).ToArray();
4
25.03.2013 10:19:36

Это расширяется после ответа от @Dunc. Смотрите комментарии в формате XML

// ReSharper disable CheckNamespace
using System.Linq;
using System.Web.Mvc;


public static class Debugg
{
    /// <summary>
    /// This class is for debugging ModelState errors either in the quick watch 
    /// window or the immediate window.
    /// When the model state contains dozens and dozens of properties, 
    /// it is impossible to inspect why a model state is invalid.
    /// This method will pull up the errors
    /// </summary>
    /// <param name="modelState">modelState</param>
    /// <returns></returns>
    public static ModelError[]  It(ModelStateDictionary modelState)
    {
        var errors = modelState.Values.SelectMany(x => x.Errors).ToArray();
        return errors;            
    }
}
4
11.10.2013 21:08:12

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

Пример использования:

if (!ModelState.IsValid)
{
    var errors = ModelState.GetModelErrors();
    return Json(new { errors });
}

Usings:

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using WebGrease.Css.Extensions;

Учебный класс:

public static class ModelStateErrorHandler
{
    /// <summary>
    /// Returns a Key/Value pair with all the errors in the model
    /// according to the data annotation properties.
    /// </summary>
    /// <param name="errDictionary"></param>
    /// <returns>
    /// Key: Name of the property
    /// Value: The error message returned from data annotation
    /// </returns>
    public static Dictionary<string, string> GetModelErrors(this ModelStateDictionary errDictionary)
    {
        var errors = new Dictionary<string, string>();
        errDictionary.Where(k => k.Value.Errors.Count > 0).ForEach(i =>
        {
            var er = string.Join(", ", i.Value.Errors.Select(e => e.ErrorMessage).ToArray());
            errors.Add(i.Key, er);
        });
        return errors;
    }

    public static string StringifyModelErrors(this ModelStateDictionary errDictionary)
    {
        var errorsBuilder = new StringBuilder();
        var errors = errDictionary.GetModelErrors();
        errors.ForEach(key => errorsBuilder.AppendFormat("{0}: {1} -", key.Key,key.Value));
        return errorsBuilder.ToString();
    }
}
5
17.06.2015 21:20:08
Спасибо CodeArtist! Я сделал небольшое изменение в коде ниже его реализации.
Alfred Severo 22.06.2015 02:20:26

В вашей реализации вам не хватает статического класса, это должно быть.

if (!ModelState.IsValid)
{
    var errors =  ModelStateErrorHandler.GetModelErrors(this.ModelState);
    return Json(new { errors });
}

скорее

if (!ModelState.IsValid)
{
    var errors = ModelState.GetModelErrors();
    return Json(new { errors });
}
0
22.06.2015 02:18:44

В случае, если кто-то хочет вернуть имя свойства модели для привязки сообщения об ошибке в строго типизированном представлении.

List<ErrorResult> Errors = new List<ErrorResult>();
foreach (KeyValuePair<string, ModelState> modelStateDD in ViewData.ModelState)
{
    string key = modelStateDD.Key;
    ModelState modelState = modelStateDD.Value;

    foreach (ModelError error in modelState.Errors)
    {
        ErrorResult er = new ErrorResult();
        er.ErrorMessage = error.ErrorMessage;
        er.Field = key;
        Errors.Add(er);
    }
}

Таким образом, вы можете связать ошибку с полем, которое выдало ошибку.

8
8.11.2018 10:03:49

Вывод только сообщений об ошибках сам по себе не был достаточным для меня, но это добилось цели.

var modelQuery = (from kvp in ModelState
                  let field = kvp.Key
                  let state = kvp.Value
                  where state.Errors.Count > 0
                  let val = state.Value?.AttemptedValue ?? "[NULL]"

                  let errors = string.Join(";", state.Errors.Select(err => err.ErrorMessage))
                  select string.Format("{0}:[{1}] (ERRORS: {2})", field, val, errors));

Trace.WriteLine(string.Join(Environment.NewLine, modelQuery));
6
29.08.2019 00:11:10
В качестве предупреждения пары ключ-значение в ModelState могут содержать значения NULL, поэтому в исходный код был включен какой-то симпатичный бизнес на C # 6 с оператором null-coalesce (?.), Отсюда и каррирование в ?? в конце выражения. Исходное выражение, которое должно защищать от нулевых ошибок, было: state.Value .?AttemptedValue ?? "[ЗНАЧЕНИЕ NULL]". Насколько я знаю, код в его текущем состоянии, без хитрой обработки случаев, когда state.Value == null, находится под угрозой.
Josh Sutterfield 9.03.2017 21:50:20

<div class="text-danger" style="direction:rtl" asp-validation-summary="All"></div>

просто используйте asp-validation-summary Tag Helper

0
24.03.2020 15:45:44