ASP.NET MVC:在TryUpdateModel中设置的验证消息未显示ValidationSummary

问题描述:

我一直在尝试遵循Web上的验证教程和示例,例如David Hayden's Blog和官方ASP.Net MVC Tutorials,但我无法获取以下代码显示实际的验证错误。如果我有一个看起来是这样的一个观点:ASP.NET MVC:在TryUpdateModel中设置的验证消息未显示ValidationSummary

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

每当我进入一个无效的年龄(因为年龄被声明为int)如“xxx”(非整数),视图确实在屏幕顶部正确显示消息“编辑失败,更正错误并重试”,以及突出显示Age文本框并放置一个红色星号在它旁边,指出错误。但是,没有错误消息列表与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); 
    } 

我错过了什么?

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

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

通知的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,因此返回任何Exception ModelError的null。所以,在这一点上,我的2个最佳工作周围的想法对这个问题有:

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

还有其他想法吗?

+1

我自己也来到了这个相同的实现,但通过一些小小的尝试和错误。你的#2大概是我最终不得不做的。 – Funka 2009-09-01 18:59:34

+0

你知道在MVC3中是否有这样做的方法?我即将创建一个全局动作过滤器,从我的异常复制到ErrorMessage属性,但似乎很奇怪,我应该! – mcintyre321 2011-09-26 14:13:07