为什么默认模型绑定器在不在表单数据中时不验证字段?

时间:2009-04-24 08:21:18

标签: asp.net-mvc

假设你有这样简单的对象:

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,而不是人们所期望的行为 那你有什么建议改变这种行为?

修改: 请记住,恶意用户可以使用FireBugTamper Data插件轻松篡改表单数据,以传递默认模型绑定程序的验证,这可能会导致一些安全问题。

4 个答案:

答案 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)

在研究了将表单值导入控制器方法的所有不同方法之后,我发现“最安全”是将每个表单字段明确定义为控制器的参数。副作用是,如果表单没有其中一个字段,它将抛出异常 - 这将解决您的问题。