Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all Errors from ASP.Net MVC modelState?

I want to get all the error messages out of the modelState without knowing the key values. Looping through to grab all the error messages that the ModelState contains.

How can I do this?

like image 212
chobo2 Avatar asked Aug 30 '09 02:08

chobo2


People also ask

How do I show ModelState error in view?

To pass error to the view we can use ModelState. AddModelError method (if the error is Model field specific) or simply ViewBag or ViewData can also be used.

Which property is used to determine an error in ModelState?

Errors property and the ModelState. IsValid property. They're used for the second function of ModelState : to store the errors found in the submitted values.


11 Answers

Using LINQ:

IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);
like image 150
mmutilva Avatar answered Sep 24 '22 12:09

mmutilva


foreach (ModelState modelState in ViewData.ModelState.Values) {
    foreach (ModelError error in modelState.Errors) {
        DoSomethingWith(error);
    }
}

See also How do I get the collection of Model State Errors in ASP.NET MVC?.

like image 45
Oren Trutner Avatar answered Sep 23 '22 12:09

Oren Trutner


Building on the LINQ verison, if you want to join all the error messages into one string:

string messages = string.Join("; ", ModelState.Values
                                        .SelectMany(x => x.Errors)
                                        .Select(x => x.ErrorMessage));
like image 23
Dunc Avatar answered Sep 22 '22 12:09

Dunc


I was able to do this using a little 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;
}

The above method returns a list of validation errors.

Further Reading :

How to read all errors from ModelState in ASP.NET MVC

like image 23
Yasser Shaikh Avatar answered Sep 23 '22 12:09

Yasser Shaikh


During debugging I find it useful to put a table at the bottom of each of my pages to show all ModelState errors.

<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>
like image 23
Simon_Weaver Avatar answered Sep 24 '22 12:09

Simon_Weaver


As I discovered having followed the advice in the answers given so far, you can get exceptions occuring without error messages being set, so to catch all problems you really need to get both the ErrorMessage and the Exception.

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

or as an extension method

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

}
like image 41
Alan Macdonald Avatar answered Sep 23 '22 12:09

Alan Macdonald


In case anyone wants to return the Name of the Model property for binding the error message in a strongly typed view.

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);
    }
}

This way you can actually tie the error in with the field that threw the error.

like image 28
james31rock Avatar answered Sep 24 '22 12:09

james31rock


Outputting just the Error messages themselves wasn't sufficient for me, but this did the trick.

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));
like image 35
Josh Sutterfield Avatar answered Sep 24 '22 12:09

Josh Sutterfield


For just in case someone need it i made and use the following static class in my projects

Usage example:

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;

Class:

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();
    }
}
like image 38
CodeArtist Avatar answered Sep 22 '22 12:09

CodeArtist


And this works too:

var query = from state in ModelState.Values
    from error in state.Errors
    select error.ErrorMessage;
var errors = query.ToArray(); // ToList() and so on...
like image 28
amiry jd Avatar answered Sep 24 '22 12:09

amiry jd


Anybody looking for asp.net core 3.1. Slightly updated than the above answer. I found that this is what [ApiController] returns

 Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();

                foreach (KeyValuePair<string, ModelStateEntry> kvp in ViewData.ModelState)
                {
                    string key = kvp.Key;
                    ModelStateEntry entry = kvp.Value;

                    if (entry.Errors.Count > 0)
                    {
                        List<string> errorList = new List<string>();
                        foreach (ModelError error in entry.Errors)
                        {
                            errorList.Add(error.ErrorMessage);
                        }

                        errors[key] = errorList;
                    }
                }

                return  new JsonResult(new {Errors = errors});
like image 5
Jivan Bhandari Avatar answered Sep 22 '22 12:09

Jivan Bhandari