属性[Bind(Exclude ="")]无法防止过度发布

Nei*_*ett 3 c# asp.net-mvc entity-framework asp.net-mvc-4 entity-framework-5

阻止MVC 4过度发布的最佳方法是什么?

根据MS消息来源,[Bind]属性应该是通过阻止传入的表单值进入数据库来防止过度发布的最简单方法.使用最新版本的MVC和EF,这似乎没有像预期/广告一样工作,除非我遗漏了一些重要的东西.

Wrox Professional ASP.NET MVC 4(Jon Galloway的第7章)开始,以下类应该防止过度发布:

[Bind(Exclude="IsAdmin")]
public class User
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public bool IsAdmin { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但是所有[Bind]属性都会阻止表单提交值绑定到模型.然后,模型具有空白/默认值,并将其写回数据库.在这种情况下,它会确保IsAdmin = false每次使用此模型调用.SaveChanges().任何"真实"值都会被覆盖.这是一个巨大的安全故障.

替代语法 - 将[Bind]放置在Edit controller action参数中 - 完全相同:

public ActionResult Edit([Bind(Exclude = "IsAdmin")] User user)
Run Code Online (Sandbox Code Playgroud)

当调用.SaveChanges()时,所有"真实"值都会被覆盖,这与K. Scott Allen关于该主题的博客文章相矛盾:http://odetocode.com/blogs/scott/archive/2012/03/11/complete-guide-对质量分配,在-ASP净mvc.aspx

唯一的选择似乎是一系列专用的ViewModel,它们都与Automapper相连.虽然安全,但这似乎是一个巨大的头痛,尤其是:

  • 您可能对"创建","编辑","索引"和"详细信息"操作有不同的要求,需要使用不同的ViewModel
  • 您可能需要在属性上显示一些只读字段(例如"编辑"操作上的CreatedBy),因为它们是由"创建"操作更新的,因此它们不具有属性上的[ReadOnly]属性

我知道有人会回应说你永远不应该将数据模型绑定到视图,但这是默认的模板行为以及它在几乎所有文档中的显示方式.此外,MVC + EF应该让生活变得更轻松,而不是更难,并且使用AutoMapper连接的ModelView类的海洋并不是我认为更容易的.

那么有谁知道如何使[Bind]功能像宣传的一样?

Pau*_*lor 5

我想你可能会在这个场合误导Wrox的书.您描述的是Bind/Exclude属性的预期行为.请参阅http://msdn.microsoft.com/en-us/library/system.web.mvc.bindattribute.exclude(v=vs.108).aspx.

如果你不想将值绑定到模型上的每个属性,我相信ViewModels是他们的方式,即使你正确地指出它们是一个开销.然而,使用它们的优势是显着的,IMO在这种情况下,证明了额外的开发工作是合理的.例如:

  • 允许部分实体更新
  • 显示来自多个实体的数据
  • 将UI与域模型分离,允许您更改标签,验证规则和错误消息

Automapper是执行从实体到视图模型的映射的一个选项,但是如果您使用的是Lazy Loading,请注意.我发现Automapper不会按照我希望的方式处理EF Proxy类的更新.最后,我删除了AM并基于IMappable接口和通用实用程序类推出了自己的映射机制.在许多情况下,输入的代码并不比配置Automapper要多得多.