【问题标题】:Interaction between Models and ViewModels in ASP.NET MVCASP.NET MVC 中模型和视图模型之间的交互
【发布时间】:2024-05-19 12:30:02
【问题描述】:

您能解释一下 ASP.NET MVC 中的交互模型和视图模型吗?

  1. 如果我需要在页面上显示数据,而不是编辑,是创建一个ViewModel来显示还是使用Model?

  2. 我在存储库中有两种方法。一个返回模型,另一个模型获取。在视图中我需要发送模型。我是否应该将生成的模型转换为将其传递给视图的 ViewModel,并在收到提交后将其转换回模型以保留它?

例如,我有一个类模型和类 ViewModel。

 public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Price { get; set; }
}

public class EditItemItemViewModel
{
    public string Name { get; set; }
    public int Price { get; set; }
}

在编辑页面,我点击了编辑项,必须到达控制器:

    [HttpGet]
    public ActionResult EditItem(int id)
    {
       //some code
        return View();
    }
  1. 如果我传入了没有ID的视图ViewModel,我在哪里可以得到ID?

  2. 如果我以某种方式获得了 ID,我需要执行以下操作,这会保存模型吗?

    [HttpPost]
    public ActionResult EditItem(EditItemItemViewModel ViewModel)
    {
    
       var Item = _dataManager.Items.GetItemById("1");
       Item.Name = ViewModel.Name;
       Item.Price = ViewModel.Price;
    
       _dataManager.Items.AddItem(Item);
    
        return View("Sucsess");
    }
    

您能告诉我如何使用模型和视图模型吗?

【问题讨论】:

    标签: c# asp.net-mvc entity-framework


    【解决方案1】:

    您可以通过几种不同的方式获取 id:

    @Html.HiddenFor(m => m.Id)
    

    这将在实际的 HTTP 请求中包含该属性。

    另一种选择是简单地将 id 包含在您的路线中(这是我通常做的):

    @Html.BeginForm("EditItem", "SomeController", new { Id = Model.Id }, FormMethod.Post) {
        ...
    }
    

    在这两种情况下,请确保验证用户应该能够更新与该 ID 对应的记录!没有什么可以阻止用户篡改 id 并向您发送不同的值。

    至于是否显示数据库模型或视图模型,这完全取决于您。我总是主张建立一个视图模型,并把你的数据库模型排除在画面之外,除了在你的控制器中。我在工作中使用的约定是对于我需要发送给用户的每个数据库对象,我将创建一个相应的视图模型。因此,如果我有一个名为 Product 的数据库对象,我将为名为 ProductModel 的视图构建另一个类。

    遵循该模式的一个优势是我之前在explained to another user 之前就模型绑定而言。

    【讨论】:

      【解决方案2】:

      如果我需要在页面上显示数据,而不是编辑,是创建一个ViewModel来显示还是使用Model?

      如果它非常简单(如您的示例)并且属性映射 1-1 就像现在一样。我只是将模型用作视图模型,它更容易。虽然如果你愿意,你可以创建一个具有完全相同属性的视图模型并填充它并显示它。这需要更多的工作,但它使你的域模型不一定与你的视图相关联。

      如果你这样做了,你可能想研究像 AutoMapper 这样的东西,它可以让你做类似的事情

      //simply copies the properties from one type to another
      var viewModel = Mapper.Map<Item, EditItemItemViewModel>();
      

      我在存储库中有两种方法。一个返回模型,另一个模型得到。在视图中我需要发送模型。我是否应该将生成的模型转换为将其传递给视图的 ViewModel,并在收到提交后将其转换回模型以保留它?

      如果您采用视图模型路线,那么是的,您最终会在模型和视图模型之间进行大量转换,这就是 AutoMapper 之类的东西可以提供帮助的地方,或者您可以创建几个扩展方法来在两者之间进行转换类型。

      看起来 Justin Helgerson 的回答解释了处理模型/视图模型的方法非常好。

      【讨论】:

        【解决方案3】:

        你发布了你的视图模型,所以我假设你已经在页面中引用了你的模型

         @model MyNameSpace.EditItemItemViewModel
        

        id 没有包含在您的视图模型中是否有原因?最简单的方法是将其包含在模型中,并在创建视图时传递实例化模型。

        [HttpGet]
        public ActionResult EditItem(int id)
        {
            var myViewModel = new EditItemItemViewModel() { Id = id }; 
            return View(myViewModel);
        }
        

        就像贾斯汀说的那样,把它放在@Html.BeginForm 内的某个隐藏字段中更容易,因为 id 应该仅供参考。

        [HttpPost]
        public ActionResult EditItem(EditItemItemViewModel viewModel)
        {
           var Item = _dataManager.Items.GetItemById(viewModel.Id);
           Item.Name = viewModel.Name;
           Item.Price = viewModel.Price;
        
           // Should this be an Add?
           _dataManager.Items.AddItem(Item);
        
            return View("Success");
        }
        

        【讨论】:

        • 谢谢,食堂把Model和ViewModel的关系搞清楚了!