我们说我们有一个
的视图模型public class NewCustomerViewModel
{
public IEnumerable<MembershipType> MembershipType { get; set; }
public Customer Customer { get; set; }
}
我们有一个form.cshtml来创建/编辑客户,下面是一些html帮助
@Html.LabelFor(e => e.Customer.Name)
@Html.TextBoxFor(e => e.Customer.Name, new { @class = "form-control" })
@Html.ValidationMessageFor(c => c.Customer.Name)
所以让我以一种简单的方式对其进行改写:
1.创建客户时,当代码执行到@ Html.ValidationMessageFor(c =&gt; c.Customer.Name)时,即使客户没有名称也没有错误
2.当保存没有名字的客户(发布表单并返回到同一视图)时,当代码执行到@ Html.ValidationMessageFor(c =&gt; c.Customer.Name)时,会出现错误,因为顾客没有名字。
所以我的问题是,为什么我在创建新客户时第一次没有错误?由于新客户没有名称(我在文本框中输入客户名称),为什么@ Html.ValidationMessageFor(c =&gt; c.Customer.Name)没有错误?
答案 0 :(得分:1)
当浏览器请求页面时,html将返回到浏览器。它将有一个标签和一个客户名称的文本框。用户将有机会输入客户名称,然后提交表单。如果用户未输入客户名称,并单击按钮提交表单,则会显示错误。根据设置方式,错误可能会显示,甚至不会离开浏览器。这称为客户端验证,使用jQuery或纯javascript完成。
如果没有客户端验证,它将进入服务器,在服务器上,asp.net mvc引擎将使用模型绑定来填充您的模型。然后,它将使用您在模型上具有的属性,并将ModelState
属性设置为有效或无效。如果代码无效,您将需要在控制器中编写代码并执行某些操作:
if(!ModelState.IsValid)
{
// Now MVC will create the error message and send
// the view back to the browser
return View(model);
}
// Model is valid so save to database or do whatever you need to.
记住一件事:即使你有客户端验证,你也应该总是在服务器端进行验证,因为如果用户关闭了javascript,客户端验证可能不会触发。或者精明的用户可以找到绕过验证的方法。
修改强>
在对此答案的评论中,您问:
ModelState和ValidationMessageFor之间的关系是什么?ModelState绑定了一个错误并将其传递给视图,然后ValidationMessageFor识别出来了吗?
ValidationMessageFor
的签名,您在问题中使用的签名是:
public static MvcHtmlString ValidationMessageFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression);
以下是您使用它的方式:
@Html.ValidationMessageFor(c => c.Customer.Name)
请参阅第二个参数expression
,其类型为Expression
。 MVC使用该信息将Customer.Name
与验证消息联系起来。将模型传递给视图时,MVC将在ModelState.Errors
中查找与Customer.Name
属性相关的任何错误。那么谁将错误放在ModelState.Errors
集合中?默认的DataAnnotations模型绑定器将使用您为其建模的装饰属性填充验证错误。然后它将呈现适当的HTML,以便浏览器向用户显示它。
这就是为什么在第一种情况下,当浏览器只是请求页面时,Errors
集合将为空,因此MVC不会将HTML呈现为错误。但是,当发布表单时,如果用户没有完成验证所需的所有操作,则MVC会将错误添加到ModelState.Errors
集合中。
我认为你的困惑部分来自我们为什么在第一次用户填写页面时甚至需要@Html.ValidationMessageFor(c => c.Customer.Name)
。答案:我们不需要它(不是真的,而是继续阅读)。我们可以在提交表单后发送不同的视图,并确保该视图具有@Html.ValidationMessageFor(c => c.Customer.Name)
。我没有看到这样的设计,它会导致代码重复(但可以避免重复...反正让我们留点)。
注意我说并不是真的,但继续阅读,这就是为什么我们可能想要@Html.ValidationMessageFor(c => c.Customer.Name)
即使在第一次显示时也是如此。在大多数情况下,验证可以在客户端完成(需要在服务器端再次完成),这对最终用户来说是更好的体验。在这种情况下,很高兴hmtl已经在视图中,然后显示/隐藏错误,使用CSS通过javascript或jQuery来装饰它。如果HTML不存在,则需要在客户端生成。实际上你甚至不需要编写用于显示/隐藏错误的代码:打开\Scripts\jquery.validate.unobtrusive.js
文件并搜索“data-val”,你会看到它使用了data-val- ,输入 - 和field- * CSS类,用于在客户端上显示/隐藏验证消息。