首页 文章

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

提问于
浏览
115

如何获取所有ModelState错误消息的列表?我找到了这个代码来获取所有密钥:(Returning a list of keys with ModelState errors

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 ...

13 回答

  • 3

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

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

    EDIT :您可以通过添加 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();
    

    2nd EDIT :您正在寻找 Dictionary<string, string[]>

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

    变量与返回类型而不是返回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;
        }
    }
    
  • 5

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

    首先创建一个扩展方法:

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

    然后调用该扩展方法并将控制器操作中的错误(如果有)作为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());
        }
    }
    
  • 2

    我喜欢在这里使用 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 });
    

    这样你得到以下回应:

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

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

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

    @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;
            }
    
  • 69

    看看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的想法

  • 171

    最简单的方法是使用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."
        ]
      }
    }
    
  • 7

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

    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;
            }
    
        }
    
    }
    
  • 1

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

    ModelState 作为Json返回,只需将其传递给Json类构造函数(与ANY对象一起使用)

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

    通过使用内置功能实现此目的的简单方法

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

    JSON result will be

  • 2

    我做了和扩展,返回字符串与分隔符“”(你可以使用自己的):

    public static string GetFullErrorMessage(this ModelStateDictionary modelState) {
            var messages = new List<string>();
    
            foreach (var entry in modelState) {
                foreach (var error in entry.Value.Errors)
                    messages.Add(error.ErrorMessage);
            }
    
            return String.Join(" ", messages);
        }
    
  • 0
    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;
    }
    

相关问题