如果ModelState.IsValid失败,会得到错误消息?


80

我的控制器中有此功能。

[HttpPost]
public ActionResult Edit(EmployeesViewModel viewModel)
{
    Employee employee = GetEmployee(viewModel.EmployeeId);
    TryUpdateModel(employee);

    if (ModelState.IsValid)
    {
        SaveEmployee(employee);
        TempData["message"] = "Employee has been saved.";
        return RedirectToAction("Details", new { id = employee.EmployeeID });
    }

    return View(viewModel); // validation error, so redisplay same view
}

它不断失败,ModelState.IsValid不断返回false并重新显示视图。但是我不知道错误是什么。

有没有办法得到错误并重新显示给用户?


Answers:


36

您可以在视图中执行此操作,而无需执行任何特殊操作,方法是使用Html.ValidationSummary()显示所有错误消息,或使用Html.ValidationMessageFor()显示模型的特定属性的消息。

如果仍然需要从操作或控制器中查看错误,请参见ModelState.Errors属性


12
没有ModelState.Errors属性?
niico '17

@niico我认为他表示的是“ ModelState”类型的属性,而Controller.ModelState属性为ModelStateDictionary类型
。– devlord

3
@niico ModelState.Error仅适用于MVC,不存在WebAPI
stuzor

146

尝试这个

if (ModelState.IsValid)
{
    //go on as normal
}
else
{
    var errors = ModelState.Select(x => x.Value.Errors)
                           .Where(y=>y.Count>0)
                           .ToList();
}

错误将是所有错误的列表。

如果要向用户显示错误,只需将模型返回视图即可,如果尚未删除Razor@Html.ValidationFor()表达式,它将显示出来。

if (ModelState.IsValid)
{
    //go on as normal
}
else
{
    return View(model);
}

该视图将在每个字段旁边和/或在ValidationSummary(如果存在)中显示任何验证错误。


86

如果您要生成一个包含ModelState错误消息的错误消息字符串,则可以SelectMany将错误拼合为一个列表:

if (!ModelState.IsValid)
{
    var message = string.Join(" | ", ModelState.Values
        .SelectMany(v => v.Errors)
        .Select(e => e.ErrorMessage));
    return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}

9
有时ErrorMessage未提供,例如,如果DateTime未设置必填字段。在这种情况下,请查找异常消息,例如e.Exception.Message
WhatIsHeDoing

有时也没有提供!我有一个ModelState带有5个错误的错误,每个错误都有一个Exception空字符串,ErrorMessage而其他条目ModelState根本就没有Errors与之相关联。
马特·阿诺德

6

如果“模态状态”无效并且由于控件处于折叠状态,则无法在屏幕上看到错误,那么您可以返回HttpStatusCode,以便在执行F12时显示实际错误消息。您也可以将此错误记录到ELMAH错误日志中。下面是代码

if (!ModelState.IsValid)
{
              var message = string.Join(" | ", ModelState.Values
                                            .SelectMany(v => v.Errors)
                                            .Select(e => e.ErrorMessage));

                //Log This exception to ELMAH:
                Exception exception = new Exception(message.ToString());
                Elmah.ErrorSignal.FromCurrentContext().Raise(exception);

                //Return Status Code:
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}

但是请注意,此代码将记录所有验证错误。因此,仅在出现无法在屏幕上看到错误的情况时才应使用此选项。


是否可以获取名称/消息对,以便我们知道哪个字段出错?
马特

4

如果有人在这里使用WebApi(不是MVC),则只需返回该ModelState对象:

return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);


2

确定检查并添加到观看:

  1. 在代码的ModelState行做一个断点
  2. 将模型状态添加到手表
  3. 展开ModelState“值”
  4. 展开值“结果视图”

现在,您可以看到所有SubKey的列表,其验证状态位于值的末尾。

因此搜索无效值


2
ModelState.Values.SelectMany(v => v.Errors).ToList().ForEach(x => _logger.Error($"{x.ErrorMessage}\n"));

1

是样品延长

public class GetModelErrors
{
    //Usage return Json to View :
    //return Json(new { state = false, message = new GetModelErrors(ModelState).MessagesWithKeys() });
    public class KeyMessages
    {
        public string Key { get; set; }
        public string Message { get; set; }
    }
    private readonly ModelStateDictionary _entry;
    public GetModelErrors(ModelStateDictionary entry)
    {
        _entry = entry;
    }

    public int Count()
    {
        return _entry.ErrorCount;
    }
    public string Exceptions(string sp = "\n")
    {
        return string.Join(sp, _entry.Values
            .SelectMany(v => v.Errors)
            .Select(e => e.Exception));
    }
    public string Messages(string sp = "\n")
    {
        string msg = string.Empty;
        foreach (var item in _entry)
        {
            if (item.Value.ValidationState == ModelValidationState.Invalid)
            {
                msg += string.Join(sp, string.Join(",", item.Value.Errors.Select(i => i.ErrorMessage)));
            }
        }
        return msg;
    }

    public List<KeyMessages> MessagesWithKeys(string sp = "<p> ● ")
    {
        List<KeyMessages> list = new List<KeyMessages>();
        foreach (var item in _entry)
        {
            if (item.Value.ValidationState == ModelValidationState.Invalid)
            {
                list.Add(new KeyMessages
                {
                    Key = item.Key,
                    Message = string.Join(null, item.Value.Errors.Select(i => sp + i.ErrorMessage))
                });
            }
        }
        return list;
    }
}

0

我不知道这是否是您的问题,但是如果您添加用户,然后更改应用程序的名称,该用户将保留在数据库中(当然),但将无效(这是正确的行为)。但是,不会为此类故障添加任何错误。错误列表为空,但ModelState.IsValid将为登录返回false。



0
publicIHttpActionResultPost(Productproduct) {  
    if (ModelState.IsValid) {  
        //Dosomethingwiththeproduct(notshown).  
        returnOk();  
    } else {  
        returnBadRequest();  
    }  
}

要么

public HttpResponseMessage Post(Product product)
        {
            if (ModelState.IsValid)
            {
                // Do something with the product (not shown).

                return new HttpResponseMessage(HttpStatusCode.OK);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
        }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.