Reputation: 85715
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?
Upvotes: 544
Views: 434535
Reputation: 9510
With fieldName ..
if (!this.ModelState.IsValid)
{
foreach (var modelState in this.ModelState)
{
foreach (var error in modelState.Value.Errors)
{
rModel.AddError(error.ErrorMessage, ErrorType.Error, modelState.Key);
}
}
rModel.Message = "Invalid Data";
return false;
}
Upvotes: 0
Reputation: 860
Anybody looking for asp.net core 3.1. The answer includes key (field name). Most of other answers include only errors.
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});
Upvotes: 7
Reputation: 111
get error with Field Name and Error Message
var errors = new List<ErrorDto>();
foreach (KeyValuePair<string, ModelStateEntry> kvp in context.ModelState)
{
if (kvp.Value.Errors.Count > 0)
{
errors.Add(new ErrorDto()
{
FieldName = kvp.Key,
ErrorMessage = string.Join(",", kvp.Value.Errors.Select(v => v.ErrorMessage))
});
}
}
Error Model
public class ErrorDto
{
public string FieldName { get; set; }
public string ErrorMessage { get; set; }
}
Upvotes: 1
Reputation: 211
This code snippet is useful too and give you a List that contains of Error Messges.
var errors = ModelState.Values.SelectMany(x => x.Errors.Select(c => c.ErrorMessage)).ToList();
Upvotes: 10
Reputation: 121
For AJAX Request better solution:
public IActionResult Demo(DemoInfo formData)
{
if (!ModelState.IsValid)
{
IEnumerable<object> formErrors = ModelState.Select((s) => new {
fieldName = s.Key,
fieldValue = s.Value.RawValue,
fieldMessage = s.Value.Errors.FirstOrDefault()?.ErrorMessage
});
return Json(new { formValid = 0, formErrors });
}
return Json(new { formValid = 1 });
}
Response format will be:
{"formValid":0,
"formErrors":[{
"fieldName":"name of field from object",
"fieldValue":"value from browser",
"fieldMessage":null /*Error message from model annotations if field is valid the value will be null */
}]
}
For more details about Func<> check this page : Func<TSource,Int32,TResult>)
Upvotes: 5
Reputation: 565
var result = string.Join(',',ModelState.Values.SelectMany(v => v.Errors).Select(a=>a.ErrorMessage));
Upvotes: -1
Reputation: 21
var x = new Dictionary<string,string>();
for (var b = 0; b < ViewData.ModelState.Values.Count(); b++)
{
if (ViewData.ModelState.Values.ElementAt(b).Errors.Count() > 0)
x.Add(ViewData.ModelState.Keys.ElementAt(b), String.Join(",", ViewData
.ModelState.Values.ElementAt(b).Errors.Select(c => c.ErrorMessage)));
}
Upvotes: 0
Reputation: 71
<div class="text-danger" style="direction:rtl" asp-validation-summary="All"></div>
simply use asp-validation-summary Tag Helper
Upvotes: 5
Reputation: 1988
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));
Upvotes: 7
Reputation: 47774
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
Upvotes: 39
Reputation: 2705
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.
Upvotes: 12
Reputation: 18994
Using LINQ:
IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);
Upvotes: 653
Reputation: 506
In your implementation you are missing static Class, this should be.
if (!ModelState.IsValid)
{
var errors = ModelStateErrorHandler.GetModelErrors(this.ModelState);
return Json(new { errors });
}
rather
if (!ModelState.IsValid)
{
var errors = ModelState.GetModelErrors();
return Json(new { errors });
}
Upvotes: -1
Reputation: 5684
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();
}
}
Upvotes: 6
Reputation: 18922
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));
Upvotes: 236
Reputation: 671
In addition, ModelState.Values.ErrorMessage
may be empty, but ModelState.Values.Exception.Message
may indicate an error.
Upvotes: 3
Reputation: 145880
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>
Upvotes: 21
Reputation: 33098
This is expanding upon the answer from @Dunc . See xml doc comments
// 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;
}
}
Upvotes: 4
Reputation: 428
Useful for passing array of error messages to View, perhaps via Json:
messageArray = this.ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors, (modelState, error) => error.ErrorMessage).ToArray();
Upvotes: 4
Reputation: 1900
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();
}
Upvotes: 16
Reputation: 27575
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...
Upvotes: 4
Reputation: 24208
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?.
Upvotes: 591