asp.net-mvc TryUpdateModel 的真实示例,ASP .NET MVC 3

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7735635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:30:56  来源:igfitidea点击:

Real example of TryUpdateModel, ASP .NET MVC 3

asp.net-mvcmodelcontroller

提问by Sir Hally

I can't understand, how to use TryUpdateModel and save the MVC architecture at the same time.

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

If I am not mistaken, work with datacontexts must be in the Model. So, such code

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

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

must be situated in the Model, not in the Controller, mustn't it?

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

But the ussual examples of TryUpdateModel usage is following:

但是 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");
    }

Doesn't this way break the MVC architecture? We work with database in the controller, not in the special Model class.

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

So, what is the best way to use TryUpdateModel in a real project?

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

回答by Ben Foster

Since the OP asked, here's an example of the ViewModel pattern, or as I like to call it - ASP.NET MVC done properly.

由于 OP 的要求,这里有一个 ViewModel 模式的示例,或者我喜欢称之为 - ASP.NET MVC 正确完成。

So why use a view specific model

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

  1. You should only pass the information to your view that it needs.
  2. Often you'll need to add additional view-meta-data (such as title/description attributes). These do not belong on your entities.
  3. Using TryUpdateModel/UpdateModel is wrong. Don't use (I'll explain why).
  4. It's very rare that your view-models will exactly match your entities. People often end up adding additional cruft to their entities or (not much better) just using ViewBag rather than strongly typed view model properties.
  5. If you're using an ORM you can run into issues with Lazy loaded properties (N+1). Your views should not issue queries.
  1. 您应该只将信息传递给它需要的视图。
  2. 通常您需要添加额外的视图元数据(例如标题/描述属性)。这些不属于您的实体。
  3. 使用 TryUpdateModel/UpdateModel 是错误的。不要使用(我会解释原因)。
  4. 您的视图模型与您的实体完全匹配是非常罕见的。人们通常最终会向他们的实体添加额外的垃圾,或者(也好不到哪里去)只使用 ViewBag 而不是强类型的视图模型属性。
  5. 如果您使用的是 ORM,您可能会遇到延迟加载属性 (N+1) 的问题。您的观点不应发出查询。

We'll start with a simple entity:

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

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

And let's say you have a simple form where the user can onlyupdate the Nameand Descriptionof the product. But you're using (the very greedy) TryUpdateModel.

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

So I use any number of tools (like Fiddler) to construct a POST myself and send the following:

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

Name=WhatverIWant&Description=UnluckyFool&Price=0

Name=WhatverIWant&Description=UnluckyFool&Price=0

Well the ASP.NET MVC model binder is going to inspect the input form collection, see that these properties exist on your entity and automatically bind them for you. So when you call "TryUpdateModel" on the entity you've just retrieved from your database, all of the matching properties will be updated (including the Price!). Time for a new option.

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

View Specific Model

查看特定型号

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

This contains just the properties we need in our view. Notice we've also added some validation attributes, display attributes and some mvc specific attributes.

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

By not being restricted in what we have in our view model it can make your views much cleaner. For example, we could render out our entire edit form by having the following in our view:

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

@Html.EditorFor(model => model)

Mvc will inspect all of those attributes we've added to our view model and automatically wire up validation, labels and the correct input fields (i.e. a textarea for description).

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

POSTing the form

发布表单

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

It's fairly obvious from this code what it does. We don't have any undesirable effects when we update our entity since we are explicitly setting properties on our entity.

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

I hope this explains the View-Model pattern enough for you to want to use it.

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

回答by Darin Dimitrov

So, such code must be situated in the Model, not in the Controller, mustn't it?

那么,这样的代码必须位于模型中,而不是控制器中,不是吗?

Not necessarily. Personally I prefer to put data access code in a repository. Then use constructor injection to pass some specific repository implementation to the controller (for example if I was using EF, I would write an EF repository implementation). So the controller will look like this:

不必要。我个人更喜欢将数据访问代码放在存储库中。然后使用构造函数注入将一些特定的存储库实现传递给控制器​​(例如,如果我使用的是 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");
    }
}