如何从ASP中获取所有错误。Net MVC modelState?

我想在不知道键值的情况下获得modelState中的所有错误消息。循环获取ModelState包含的所有错误消息。

我该怎么做呢?

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

另见我如何在ASP中获得模型状态错误的集合。净MVC吗?

使用LINQ:

IEnumerable<ModelError> allErrors = ModelState.Values.SelectMany(v => v.Errors);

基于LINQ版本,如果你想将所有错误消息连接到一个字符串中:

string messages = string.Join("; ", ModelState.Values
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage));

这个也有用:

var query = from state in ModelState.Values
from error in state.Errors
select error.ErrorMessage;
var errors = query.ToArray(); // ToList() and so on...

此外,ModelState.Values.ErrorMessage可能为空,但ModelState.Values.Exception.Message可能表示错误。

我可以用一点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;
}

上面的方法返回一个验证错误列表。

进一步阅读:

如何在ASP中读取ModelState中的所有错误。NET MVC < / >

在调试过程中,我发现在每个页面的底部放置一个表来显示所有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>

我发现,按照到目前为止给出的答案中的建议,可以在不设置错误消息的情况下获得发生异常的情况,因此要捕获所有问题,确实需要同时获取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();


}

用于将错误消息数组传递给View,可能通过Json:

messageArray = this.ViewData.ModelState.Values.SelectMany(modelState => modelState.Errors, (modelState, error) => error.ErrorMessage).ToArray();

这是对@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;
}
}

为了以防有人需要它,我在我的项目中创建并使用下面的静态类

使用的例子:

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

在你的实现中,你丢失了静态类,这应该是

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

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

如果有人想返回Model属性的Name,以便将错误消息绑定到强类型视图中。

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

通过这种方式,您可以将错误与抛出错误的字段绑定在一起。

仅仅输出错误消息本身对我来说是不够的,但是这样做达到了目的。

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

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

simply use asp-validation-summary Tag Helper

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

任何人在寻找asp.net core 3.1。比上面的答案略有更新。我发现这就是[ApiController]返回的内容

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

var result = string.Join(',',ModelState.Values。SelectMany (v =比;v.Errors) .Select(=祝辞a.ErrorMessage));

对于AJAX请求更好的解决方案:

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

回应格式为:

{"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 */
}]
}

关于Func<>检查本页:Func< TSource Int32, TResult>)

这个代码片段也很有用,它为您提供了一个包含错误消息的列表。

var errors = ModelState.Values.SelectMany(x => x.Errors.Select(c => c.ErrorMessage)).ToList();

使用字段名和错误消息获取错误

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


误差模型

    public class ErrorDto
{
public string FieldName { get; set; }
public string ErrorMessage { get; set; }
}