2

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

<%@ 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”(非整数)时,视图在屏幕顶部正确显示消息“Edit was unsuccessful. Correct errors and retry” ,以及突出显示年龄文本框并在其旁边放置一个红色星号,表示错误。但是,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);
    }

我错过了什么?

4

1 回答 1

2

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

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

请注意,传递了 modelState 的 null 参数。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,因此 null 是为任何异常 ModelError 返回。因此,在这一点上,我对这个问题的 2 个最佳解决方法是:

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

还有其他想法吗?

于 2009-09-01T18:48:50.400 回答