ASP.NET MVC如何将ModelState错误转换为json

如何获得所有ModelState错误消息的列表? 我发现这个代码得到所有的键:( 返回与ModelState错误键的列表 )

var errorKeys = (from item in ModelState where item.Value.Errors.Any() select item.Key).ToList(); 

但是,我怎么会得到错误消息作为IList或IQueryable?

我可以去:

 foreach (var key in errorKeys) { string msg = ModelState[error].Errors[0].ErrorMessage; errorList.Add(msg); } 

但是,这是做手动 – 当然有一种方法来使用LINQ? .ErrorMessage属性到目前为止,我不知道如何编写LINQ链…

你可以把你想要的东西放在select子句中:

 var errorList = (from item in ModelState where item.Value.Errors.Any() select item.Value.Errors[0].ErrorMessage).ToList(); 

编辑 :您可以提取多个错误到单独的列表项目,通过添加一个from子句,如下所示:

 var errorList = (from item in ModelState.Values from error in item.Errors select error.ErrorMessage).ToList(); 

要么:

 var errorList = ModelState.Values.SelectMany(m => m.Errors) .Select(e => e.ErrorMessage) .ToList(); 

第二nd编辑 :你正在寻找一个Dictionary<string, string[]>

 var errorList = ModelState.ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray() ); 

以下是将所有部分放在一起的完整实施:

首先创build一个扩展方法:

 public static class ModelStateHelper { public static IEnumerable Errors(this ModelStateDictionary modelState) { if (!modelState.IsValid) { return modelState.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Errors .Select(e => e.ErrorMessage).ToArray()) .Where(m => m.Value.Count() > 0); } return null; } } 

然后调用该扩展方法,并从控制器操作(如果有的话)返回错误为json:

 if (!ModelState.IsValid) { return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet); } 

最后,在客户端显示这些错误(以jquery.validation风格,但可以轻松地更改为任何其他风格)

 function DisplayErrors(errors) { for (var i = 0; i < errors.length; i++) { $("<label for='" + errors[i].Key + "' class='error'></label>") .html(errors[i].Value[0]).appendTo($("input#" + errors[i].Key).parent()); } } 

我喜欢在这里使用Hashtable ,这样我就可以获得JSON对象,其中的属性作为键和错误作为string数组forms的值。

 var errors = new Hashtable(); foreach (var pair in ModelState) { if (pair.Value.Errors.Count > 0) { errors[pair.Key] = pair.Value.Errors.Select(error => error.ErrorMessage).ToList(); } } return Json(new { success = false, errors }); 

这样你得到以下回应:

 { "success":false, "errors":{ "Phone":[ "The Phone field is required." ] } } 

有很多不同的方法来做到这一点,所有的工作。 这是我现在做的

 if (ModelState.IsValid) { return Json("Success"); } else { return Json(ModelState.Values.SelectMany(x => x.Errors)); } 

@JK它帮了我很多,但为什么不呢:

  public class ErrorDetail { public string fieldName = ""; public string[] messageList = null; } 

  if (!modelState.IsValid) { var errorListAux = (from m in modelState where m.Value.Errors.Count() > 0 select new ErrorDetail { fieldName = m.Key, errorList = (from msg in m.Value.Errors select msg.ErrorMessage).ToArray() }) .AsEnumerable() .ToDictionary(v => v.fieldName, v => v); return errorListAux; } 

ToDictionary是System.Linq中find的Enumerable扩展,打包在System.Web.Extensions dll http://msdn.microsoft.com/en-us/library/system.linq.enumerable.todictionary.aspx中; 。 这是完整的课程对我来说的样子。

 using System.Collections; using System.Web.Mvc; using System.Linq; namespace MyNamespace { public static class ModelStateExtensions { public static IEnumerable Errors(this ModelStateDictionary modelState) { if (!modelState.IsValid) { return modelState.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()).Where(m => m.Value.Count() > 0); } return null; } } } 

看看System.Web.Http.Results.OkNegotiatedContentResult。

它把你所投入的东西转换成JSON。

所以我做了这个

 var errorList = ModelState.ToDictionary(kvp => kvp.Key.Replace("model.", ""), kvp => kvp.Value.Errors[0].ErrorMessage); return Ok(errorList); 

这导致:

 { "Email":"The Email field is not a valid e-mail address." } 

我还没有检查,当每个字段有多个错误时会发生什么,但重点是OkNegoriatedContentResult是辉煌!

从@SLaks获得了linq / lambda的想法

最简单的方法是使用ModelState本身返回一个BadRequest

例如在一个PUT

 [HttpPut] public async Task<IHttpActionResult> UpdateAsync(Update update) { if (!ModelState.IsValid) { return BadRequest(ModelState); } // perform the update return StatusCode(HttpStatusCode.NoContent); } 

如果我们在例如手机号码上使用数据注释,就像这样,在Update类中:

 public class Update { [StringLength(22, MinimumLength = 8)] [RegularExpression(@"^\d{8}$|^00\d{6,20}$|^\+\d{6,20}$")] public string MobileNumber { get; set; } } 

这将返回一个无效的请求以下内容:

 { "Message": "The request is invalid.", "ModelState": { "update.MobileNumber": [ "The field MobileNumber must match the regular expression '^\\d{8}$|^00\\d{6,20}$|^\\+\\d{6,20}$'.", "The field MobileNumber must be a string with a minimum length of 8 and a maximum length of 22." ] } } 

与返回types的差异,而不是返回IEnumerable

 public static class ModelStateHelper { public static IEnumerable<KeyValuePair<string, string[]>> Errors(this ModelStateDictionary modelState) { if (!modelState.IsValid) { return modelState .ToDictionary(kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()) .Where(m => m.Value.Any()); } return null; } } 

为什么不将原始的ModelState对象返回给客户端,然后使用jQuery读取值。 对我来说,它看起来更简单,并使用通用数据结构(.net的ModelState

以Jsonforms返回ModelState ,只需将它传递给Json类的构造函数(与任何对象一起使用)

C#:

 return Json(ModelState); 

JS:

  var message = ""; if (e.response.length > 0) { $.each(e.response, function(i, fieldItem) { $.each(fieldItem.Value.Errors, function(j, errItem) { message += errItem.ErrorMessage; }); message += "\n"; }); alert(message); } 
  List<ErrorList> Errors = new List<ErrorList>(); //test errors. var modelStateErrors = this.ModelState.Keys.SelectMany(key => this.ModelState[key].Errors); foreach (var x in modelStateErrors) { var errorInfo = new ErrorList() { ErrorMessage = x.ErrorMessage }; Errors.Add(errorInfo); } 

如果你使用jsonresult然后返回

 return Json(Errors); 

或者你可以简单地返回modelStateErrors,我还没有尝试过。 我所做的是将Errors集合分配给我的ViewModel,然后循环它。在这种情况下,我可以通过json返回我的错误。 我有一个类/模型,我想获得源/关键,但我仍然试图弄清楚。

  public class ErrorList { public string ErrorMessage; }