C# 属性[Bind(Exclude=";)]无法防止过度过帐
防止MVC4过度发布的最佳方法是什么 据MS sources称,[Bind]属性被认为是通过防止传入表单值进入数据库来防止过度发布的最简单方法。在最新版本的MVC&EF中,这似乎没有达到预期/宣传的效果,除非我遗漏了一些重要的东西 从Wrox Professional ASP.NET MVC 4(Jon Galloway的第7章)中,以下类应防止过度发布:C# 属性[Bind(Exclude=";)]无法防止过度过帐,c#,asp.net-mvc,entity-framework,asp.net-mvc-4,entity-framework-5,C#,Asp.net Mvc,Entity Framework,Asp.net Mvc 4,Entity Framework 5,防止MVC4过度发布的最佳方法是什么 据MS sources称,[Bind]属性被认为是通过防止传入表单值进入数据库来防止过度发布的最简单方法。在最新版本的MVC&EF中,这似乎没有达到预期/宣传的效果,除非我遗漏了一些重要的东西 从Wrox Professional ASP.NET MVC 4(Jon Galloway的第7章)中,以下类应防止过度发布: [Bind(Exclude="IsAdmin")] public class User { public int ID { get;
[Bind(Exclude="IsAdmin")]
public class User
{
public int ID { get; set; }
public string FirstName { get; set; }
public bool IsAdmin { get; set; }
}
但是[Bind]属性所做的只是阻止表单提交值绑定到模型。然后,模型有一个空白/默认值,该值将写回数据库。在这种情况下,每次使用此模型调用.SaveChanges()时,它都会确保IsAdmin=false。任何“真”值都将被覆盖。这是一个巨大的安全故障
替代语法-将[Bind]放置在编辑控制器操作参数中-执行完全相同的操作:
public ActionResult Edit([Bind(Exclude = "IsAdmin")] User user)
调用.SaveChanges()时,所有“true”值都会被覆盖,这与K.Scott Allen关于以下主题的博客文章相矛盾:
唯一的选择似乎是一系列专用的ViewModels,它们都与Automapper连接在一起。虽然安全,但这似乎是一个巨大的头痛,特别是:
- 您可能对创建、编辑、索引和详图操作有不同的要求,需要不同的ViewModel
- 您可能需要公开某些只读字段(例如编辑操作上的CreatedBy),这些字段不能在属性上具有[ReadOnly]属性,因为它们由创建操作更新
那么,有人知道如何使[Bind]发挥广告所宣传的功能吗?我想你可能被这本书误导了。您描述的是绑定/排除属性的预期行为。看 如果您不想将值绑定到模型上的每个属性,我相信ViewModels是一个不错的选择,尽管正如您正确指出的那样,它们是一种开销。尽管如此,使用它们的优势是显著的,在这种情况下,IMO有理由进行额外的开发工作。例如:
- 允许部分实体更新
- 显示来自多个实体的数据
- 将UI与域模型分离,允许您更改标签、验证规则和错误消息
Automapper是从实体映射到视图模型的一个选项,但是如果您使用的是延迟加载,请小心。我发现Automapper没有像我希望的那样处理EF代理类的更新。最后,我删除了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);
}
谢谢,很好的建议,但是有几个问题/评论:1)当您将数据迁移到实体模型时,您仍然存在null over posting问题。即使该数据不在视图模型中,该属性也在数据模型中,如果EF始终发送所有字段,则将覆盖现有数据。2) Galloway和Allen是MVC文档中最有名的两位,他们都非常清楚,[Bind]是最简单的解决方案。它们都是完全错误的,还是有什么改变了?进一步思考,我开始认为问题在于
db.Entry(model).State=EntityState.Modified代码>用于告诉EF记录已更改的语法。这会在整个记录上设置状态,包括未绑定的属性,从而引入一个严重的问题。如果EF只在绑定字段上设置.IsModified(荣誉[Bind]),则事情将起作用。有人知道这是否是EF 5中的新行为吗?@Neil Laslett对于插入,任何不在视图模型中的数据都将获得默认值,或者需要在保存之前由控制器指定值。对于更新,我使用的技术是检索要更新的记录,然后从视图模型应用新值。如果您关心并发性,请在viewmodel中使用时间戳字段。@Neil Laslett。好了,绑定功能没有任何变化。如果您仔细想想,如果您的模型包含的字段在绑定时没有从表单中获取值,.NET在实例化绑定器中的对象时必须给它们一个值(数据类型的默认值)。如果将这些字段设置为可为null的类型,则在绑定后,如果这些字段没有收到值,它们将为null。如果需要,您可以检测此类字段并在保存处理中不应用更新。我希望EF在生成SQL更新和荣誉[Bind]时会更聪明,即使模型中存在属性。根据您的建议,鉴于模型的复杂性,默认的编辑操作似乎不可用。您检索现有值并根据该值进行绑定的方法(因此EF确实知道修改了什么)似乎是最好的方法。