属性无法防止过度发布

阻止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; } } 

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

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

 public ActionResult Edit([Bind(Exclude = "IsAdmin")] User user) 

当调用.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]function?

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

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

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

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

如果你恢复到manuel模型绑定,你应该没有任何问题。 如果您没有为“IsAdmin”输入输入,您的模型将保留其原始值。 这增加了一些额外的代码,但是由于不生成不维护ViewModels而节省了大量时间。

 [HttpPost] [ValidateAntiForgeryToken] public ActionResult Edit(Guid id, FormCollection collection) { var user = db.Users.Find(id); if (user != null) TryUpdateModel(user); else return HttpNotFound(); if (ModelState.IsValid) { db.SaveChanges(); return RedirectToAction("Index"); } return View(user); }