TryUpdateModel,ASP .NET MVC 3的真实示例

时间:2011-10-12 05:26:27

标签: asp.net-mvc model controller

我无法理解,如何使用TryUpdateModel并同时保存MVC架构。

如果我没弄错,使用datacontexts必须在模型中。所以,这样的代码

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的最佳方法是什么?

2 个答案:

答案 0 :(得分:112)

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

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

  1. 您只应将信息传递给您需要的视图。
  2. 通常您需要添加其他视图元数据(例如标题/描述属性)。这些不属于您的实体。
  3. 使用TryUpdateModel / UpdateModel是错误的。不要使用(我会解释原因)。
  4. 您的视图模型与您的实体完全匹配的情况非常罕见。人们经常最终只是使用ViewBag而不是强类型的视图模型属性,为他们的实体添加额外的内容或者(并不是更好)。
  5. 如果您使用的是ORM,则可能会遇到延迟加载属性(N + 1)的问题。您的观点不应发出查询。
  6. 我们将从一个简单的实体开始:

    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)自己构建一个POST并发送以下内容:

      

    名称= WhatverIWant&安培;描述= UnluckyFool&安培;价格= 0

    ASP.NET MVC模型绑定器将检查输入表单集合,看到您的实体上存在这些属性并自动为您绑定它们。因此,当您刚刚从数据库中检索到的实体上调用“TryUpdateModel”时,将更新所有匹配的属性(包括Price!)。是时候换新选择了。

    查看特定模型

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

    这只包含我们在视图中需要的属性。请注意,我们还添加了一些验证属性,显示属性和一些mvc特定属性。

    不受我们在视图模型中的限制,它可以使您的视图更清晰。例如,我们可以通过在视图中包含以下内容来渲染我们的整个编辑表单:

    @Html.EditorFor(model => model)
    

    Mvc将检查我们添加到视图模型中的所有属性,并自动连接验证,标签和正确的输入字段(即用于描述的文本区域)。

    发布表单

    [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)
    }
    

    从这段代码中可以看出它的作用。我们更新实体时没有任何不良影响,因为我们在实体上明确设置了属性。

    我希望这能够解释View-Model模式,足以让你想要使用它。

答案 1 :(得分:19)

  

那么,这样的代码必须位于模型中,而不是在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");
    }
}