【问题标题】:ASP.NET MVC: Validation messages set in TryUpdateModel not showning ValidationSummaryASP.NET MVC:在 TryUpdateModel 中设置的验证消息未显示 ValidationSummary
【发布时间】:2010-11-24 15:33:46
【问题描述】:

我一直在尝试遵循网络上的验证教程和示例,例如来自David Hayden's Blog 和官方ASP.Net MVC Tutorials,但我无法获得以下代码来显示实际的验证错误。如果我的视图看起来像这样:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication1.Models.Parent>" %>

<%-- ... content stuff ... --%>

<%= Html.ValidationSummary("Edit was unsuccessful. Correct errors and retry.") %>
<% using (Html.BeginForm()) {%>

<%-- ... "Parent" editor form stuff... --%>

        <p>
            <label for="Age">Age:</label>
            <%= Html.TextBox("Age", Model.Age)%>
            <%= Html.ValidationMessage("Age", "*")%>
        </p>

<%-- etc... --%>

对于一个看起来像这样的模型类:

public class Parent
{
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public int Age { get; set; }
    public int Id { get; set; }
}

每当我输入无效的 Age(因为 Age 被声明为 int),例如“xxx”(非整数)时,视图确实正确显示消息“编辑失败。正确错误并重试”,以及突出显示“年龄”文本框并在其旁边放置一个红色星号,表示错误。但是,ValidationSummary 不会显示错误消息列表。当我自己进行验证时(例如:下面的 LastName),消息显示正确,但 TryUpdateModel 的内置验证似乎在字段具有非法值时不显示消息。

这是在我的控制器代码中调用的操作:

    [AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult EditParent(int id, FormCollection collection)
    {
        // Get an updated version of the Parent from the repository:
        Parent currentParent = theParentService.Read(id);

        // Exclude database "Id" from the update:
        TryUpdateModel(currentParent, null, null, new string[]{"Id"});
        if (String.IsNullOrEmpty(currentParent.LastName))
            ModelState.AddModelError("LastName", "Last name can't be empty.");
        if (!ModelState.IsValid)
            return View(currentParent);

        theParentService.Update(currentParent);
        return View(currentParent);
    }

我错过了什么?

【问题讨论】:

    标签: c# asp.net-mvc validationsummary


    【解决方案1】:

    我下载并查看了来自 Microsoft 的 ASP.NET MVC v1.0 source code,发现无论是出于偶然还是有意为之,至少在默认情况下,没有办法做我想做的事情。显然,在调用 UpdateModel 或 TryUpdateModel 期间,如果整数(例如)验证失败,则不会在与 ModelState 关联的 ModelError 中为错误值显式设置 ErrorMessage,而是设置 Exception 属性。根据 MVC ValidationExtensions 中的代码,以下代码用于获取错误文本:

    string errorText = GetUserErrorMessageOrDefault(htmlHelper.ViewContext.HttpContext, modelError, null /* modelState */);
    

    请注意传递了模型状态的空参数。 GetUserErrorMEssageOrDefault 方法开始如下:

    private static string GetUserErrorMessageOrDefault(HttpContextBase httpContext, ModelError error, ModelState modelState) {
        if (!String.IsNullOrEmpty(error.ErrorMessage)) {
            return error.ErrorMessage;
        }
        if (modelState == null) {
            return null;
        }
    
        // Remaining code to fetch displayed string value...
    }
    

    所以,如果 ModelError.ErrorMessage 属性为空(我验证它是在尝试将非整数值设置为声明的 int 时),MVC 继续检查 ModelState,我们已经发现它为 null,因此任何异常 ModelError 都会返回 null。因此,在这一点上,我对这个问题的 2 个最佳解决方法是:

    1. 创建一个自定义验证扩展,在未设置 ErrorMessage 但设置了异常时正确返回适当的消息。
    2. 如果 ModelState.IsValid 返回 false,则创建一个在控制器中调用的预处理函数。预处理函数将在未设置 ErrorMessage 但设置了 Exception 的 ModelState 中查找值,然后使用 ModelState.Value.AttemptedValue 导出适当的消息。

    还有其他想法吗?

    【讨论】:

    • 我自己也有同样的认识,但经过了一些尝试和错误。你的 #2 大致就是我最终不得不做的。
    • 你知道在 MVC3 中是否有这样做的方法吗?我即将创建一个全局操作过滤器,它将我的异常复制到 ErrorMessage 属性,但我应该这样做似乎很奇怪!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 2012-08-24
    • 2019-04-10
    • 2016-04-20
    • 2016-03-29
    相关资源
    最近更新 更多