TryUpdateModel,ASP .NET MVC 3的实例

我不明白,如何使用TryUpdateModel并同时保存MVC体系结构。

如果我没有弄错,那么使用数据上下文必须在模型中。 所以,这样的代码

var db=new TestEverybody();//it is class, which was generated by EntityFramework var currentTesting=db.Testing.(t => t.id == id).First(); 

必须位于模型中,而不是在控制器中,不是吗?

但是TryUpdateModel用法的例子如下:

  public ActionResult Edit(Testing obj)//Testing collection { var db = new TestEverybody(); var currentTesting=db.Testing.(t => t.id == obj.id).First(); TryUpdateModel(currentTesting); db.SaveChanges(); return RedirectToAction("Index"); } 

这不是打破了MVC架构吗? 我们在控制器中使用数据库,而不是在特殊的Model类中。

那么,在实际项目中使用TryUpdateModel的最佳方法是什么?

由于OP问,这里是一个ViewModel模式的例子,或者我喜欢称之为ASP.NET MVC正确完成。

那么为什么要使用视图特定的模型

  1. 你只应该把信息传递给你需要的视图。
  2. 通常你需要添加额外的视图元数据(比如标题/描述属性)。 这些不属于你的实体。
  3. 使用TryUpdateModel / UpdateModel是错误的。 不要使用(我会解释为什么)。
  4. 您的视图模型与您的实体完全匹配是非常罕见的。 人们通常最终会添加更多的实体,或者使用ViewBag而不是强types的视图模型属性。
  5. 如果您使用的是ORM,则可能遇到Lazy加载属性(N + 1)的问题。 您的意见不应该发出查询。

我们将从一个简单的实体开始:

 public class Product { public int Id {get;set;} public string Name {get;set;} public string Description {get;set;} public decimal Price {get;set;} } 

假设您有一个简单的表单,用户只能更新产品的NameDescription 。 但是你正在使用(非常贪婪的)TryUpdateModel。

所以我使用任意数量的工具(如Fiddler)来自己构build一个POST,并发送以下内容:

NAME = WhatverIWant和说明= UnluckyFool及价格= 0

那么ASP.NET MVC模型联编程序将检查input表单集合,请参阅您的实体上存在这些属性,并自动为您绑定它们。 因此,当您从数据库中检索到的实体上调用“TryUpdateModel”时,所有匹配的属性都将被更新(包括Price!)。 时间一个新的select。

查看特定模型

 public class EditProductViewModel { [HiddenInput] public Guid Id {get;set;} [Required] [DisplayName("Product Name")] public string Name {get;set;} [AllowHtml] [DataType(DataType.MultilineText)] public string Description {get;set;} } 

这只包含我们需要的属性。 注意我们还添加了一些validation属性,显示属性和一些特定于mvc的属性。

通过不受我们视图模型中的限制,它可以使您的观点更清晰。 例如,我们可以通过在我们的视图中具有以下内容来呈现我们的整个编辑表单:

 @Html.EditorFor(model => model) 

Mvc将检查我们添加到视图模型中的所有属性,并自动连接validation,标签和正确的input字段(即用于描述的textarea)。

张贴表单

 [HttpPost] public ActionResult EditProduct(EditProductViewModel model) { var product = repository.GetById(model.Id); if (product == null) { return HttpNotFound(); } // input validation if (ModelState.IsValid) { // map the properties we **actually** want to update product.Name = model.Name; product.Description = model.Description; repository.Save(product); return RedirectToAction("index"); } return View(model) } 

这个代码很明显的performance了它的function。 当我们更新我们的实体时,我们没有任何不良影响,因为我们明确地设置了实体的属性。

我希望这个解释视图模型模式足够你想要使用它。

所以,这样的代码必须位于模型中,而不是在Controller中,不是吗?

不必要。 我个人更喜欢将数据访问代码放入存储库。 然后使用构造函数注入来传递一些特定的知识库实现到控制器(例如,如果我使用EF,我会写一个EF知识库实现)。 所以控制器将如下所示:

 public class HomeController: Controller { private readonly IMyRepository _repository; public HomeController(IMyRepository repository) { _repository = repository; } public ActionResult Edit(int id) { var currentTesting = _repository.GetTesting(id); TryUpdateModel(currentTesting); _repository.SaveChanges(); return RedirectToAction("Index"); } }