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

JK.*_*JK. 123 c# linq asp.net-mvc modelstate

如何获取所有ModelState错误消息的列表?我找到了这个代码来获取所有密钥:( 返回带有ModelState错误的密钥列表)

var errorKeys = (from item in ModelState
        where item.Value.Errors.Any() 
        select item.Key).ToList();
Run Code Online (Sandbox Code Playgroud)

但是,如何将错误消息作为IList或IQueryable获取?

我可以去:

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

但那可以手动完成 - 当然有一种方法可以使用LINQ吗?.ErrorMessage属性到目前为止,我不知道如何编写LINQ ...

SLa*_*aks 184

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

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

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

var errorList = (from item in ModelState.Values
        from error in item.Errors
        select error.ErrorMessage).ToList();
Run Code Online (Sandbox Code Playgroud)

要么:

var errorList = ModelState.Values.SelectMany(m => m.Errors)
                                 .Select(e => e.ErrorMessage)
                                 .ToList();
Run Code Online (Sandbox Code Playgroud)

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

var errorList = ModelState.ToDictionary(
    kvp => kvp.Key,
    kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray()
);
Run Code Online (Sandbox Code Playgroud)

  • 添加`.Where(kvp => kvp.Value.Errors.Count> 0)` (3认同)
  • 要获得与Request.CreateErrorResponse(HttpStatusCode.BadRequest,ModelState);相同的输出,应使用var errorList = modelState.Where(elem =&gt; elem.Value.Errors.Any()).ToDictionary(kvp =&gt; kvp.Key,kvp =&gt; kvp.Value.Errors.Select(e =&gt; string.IsNullOrEmpty(e.ErrorMessage)?e.Exception.Message:e.ErrorMessage).ToArray());`否则,您将没有ExceptionMessages (3认同)

JK.*_*JK. 73

这是完整的实现,所有部分放在一起:

首先创建一个扩展方法:

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.Any());
        }
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

if (!ModelState.IsValid)
{
    return Json(new { Errors = ModelState.Errors() }, JsonRequestBehavior.AllowGet);
}
Run Code Online (Sandbox Code Playgroud)

最后,在客户端显示这些错误(以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());
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 根据你的偏好`.Where(m => m.Value.Count()> 0)`也可以写成`.Where(m => m.Value.Any())`. (8认同)

小智 22

我喜欢在Hashtable这里使用,所以我得到JSON对象,其属性为键,错误为字符串数组形式的值.

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 });
Run Code Online (Sandbox Code Playgroud)

这样你得到以下回应:

{
   "success":false,
   "errors":{
      "Phone":[
         "The Phone field is required."
      ]
   }
}
Run Code Online (Sandbox Code Playgroud)


Dea*_*rth 7

有很多不同的方法可以做到这一点.现在我这样做......

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

  • 您还可以返回`BadRequest(ModelState)`,它会将它序列化为JSON. (2认同)

Eri*_*oen 7

最简单的方法是只返回BadRequest带有 ModelState 本身的 a :

例如在一个PUT

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

    // perform the update

    return StatusCode(HttpStatusCode.NoContent);
}
Run Code Online (Sandbox Code Playgroud)

如果我们在类中使用例如手机号码的数据注释,如下所示Update

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

这将针对无效请求返回以下内容:

{
  "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."
    ]
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 给新观众的注意事项:BadRequest 现在可在 .NET Core 及以上版本中使用 (3认同)
  • BadRequest 是特定于 WebAPI 的,这个问题是关于 MVC 的。 (2认同)

小智 5

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

 public class ErrorDetail {

        public string fieldName = "";
        public string[] messageList = null;
 }
Run Code Online (Sandbox Code Playgroud)
        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;
        }
Run Code Online (Sandbox Code Playgroud)


Nis*_*fan 5

通过使用内置功能实现这一点的简单方法

[HttpPost]
public IActionResult Post([FromBody]CreateDoctorInput createDoctorInput) {
    if (!ModelState.IsValid) {
        return BadRequest(ModelState);
    }

    //do something
}
Run Code Online (Sandbox Code Playgroud)

JSON 结果将是