假设你有这样简单的对象:
public class MyObject {
public int Test { get; set; }
}
您依靠默认的模型绑定器来确保用户在发布如下表单时不会将“测试”字段留空:
<form method="post" action="/test">
<p>
<%=Html.TextBox("Test") %>
<%=Html.ValidationMessage("Test") %>
</p>
<input id="Submit1" type="submit" value="submit" />
</form>
这个动作:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Test(MyObject o) {
return View();
}
当表单数据包含“测试”键(例如“Test=val
”或“Test=
”)
但是如果密钥不在表单数据中,则不会进行验证。因此,如果空的发布请求或带有AnotherField=foo
之类数据的请求,则模型对象上的属性默认为类型的默认值(在本例中为0)。 ModelState.IsValid
返回true。
这就是IMO,而不是人们所期望的行为 那你有什么建议改变这种行为?
修改: 请记住,恶意用户可以使用FireBug或Tamper Data插件轻松篡改表单数据,以传递默认模型绑定程序的验证,这可能会导致一些安全问题。
答案 0 :(得分:2)
遗憾的是,它没有按设计验证字段。请查看我发现并评论过的Codeplex issue。
非常不幸的是,MS已经确定这是他们的模型绑定器的正确行为。
我认为默认的模型绑定器应该验证整个实体而不仅仅是发布的数据。
答案 1 :(得分:1)
您可以考虑使用xVal来执行客户端和服务器端验证的必要组合。有了它,您可以向Test属性添加一个属性,指示适用于哪种验证规则(必需,正则表达式验证等),然后通过更多工作,让它为您生成JavaScript规则以及非常容易执行模型验证。
您已经意识到自己违反了开发规则 - 从不信任客户输入。真的没办法解决它。
客户端验证(防止往返发现存在错误)是很好的,服务器端验证验证事情是否真正有序是必须的。
答案 2 :(得分:0)
我希望它的设计因为我即将开始依赖这种行为!
在一个实例中,我有两个控件回发以下字段:
ShippingAddress.FirstName
ShippingAddress.LastName
ShippingAddress.Line1
ShippingAddress.Line2
BillingAddress.Email
BillingAddress.FirstName
BillingAddress.LastName
BillingAddress.Line1
BillingAddress.Line2
注意:结算地址没有显示电子邮件,即使基础模型当然还有它
如果我在我的模型中将电子邮件作为[必需]数据注释,那么只有在结算地址中缺少电子邮件时才会抱怨。
但我绝对明白你的观点!我只是依靠它来实现这一个场景!
答案 3 :(得分:0)
在研究了将表单值导入控制器方法的所有不同方法之后,我发现“最安全”是将每个表单字段明确定义为控制器的参数。副作用是,如果表单没有其中一个字段,它将抛出异常 - 这将解决您的问题。