总是在MVC中使用ViewModel模式?

Ric*_*olo 7 c# asp.net-mvc asp.net-mvc-viewmodel asp.net-mvc-5

在控制器的MVC中,您应该从DB获取Model并将其转换为ViewModel,然后再将其发送到View.通常使用像Automapper这样的东西.

我的问题是,如果你需要在视图中显示模型的所有属性,是否值得创建一个ViewModel?

如果Model和ViewModel需要相同,那么创建ViewModel会在应用程序中创建一些安全性或好处,或者我们只是增加了不必要的复杂性?

Jam*_*mes 8

使用视图模型的关键通常是因为您的视图需要比域模型提供的信息更多/更少的信息.

其他好处包括将您的视图与您的域分离,如果您的域名发展,这可能会导致其脆弱.

它的关键是,它们不是必需品; 视图模型的目的是为视图提供渲染自身所需的信息,如果您认为应用程序中的视图模型是多余的,则不要使用它.但是,我至少会考虑使用接口来避免耦合.


Yog*_*raj 6

除了已经提到的(关注点分离,解耦等)之外,单独的ViewModel会阻止可能与DB模型一起出现的抽象泄漏.如果您在启用导航属性的情况下使用EF,则尤其如此.

假设你有汽车和轮子.您正在视图中显示汽车.

案例1(没有单独的ViewModel适用于汽车):在剃须刀视图中,很容易得到类似下面的内容:

  public class CarModelFromDB
  {
      public string CarName{get;set;}
      //More properties
      public IEnumerable<Wheel> Wheel{get;set;}
  }  

  @model IEnumerable<CarModelFromDB>

  @foreach(var car in Model)
  {
      //some View Code
      @foreach(var wheel in car.Wheels.Where(x=>x.IsRound=true))
      {
         <span>wheel.Color</span> 
         // some View Code
      }
  }
Run Code Online (Sandbox Code Playgroud)

现在,您获取车轮的逻辑已泄漏到视图中,并且还启用了选择N + 1的情况.我认为没有任何简单的测试方法.

案例2(使用ViewModel对于汽车):在这种情况下,您可以通过仅发送所需的内容来限制视图.它可能如下所示:

  public class CarViewModel
  {
      public string CarName{get;set;}
      //More properties
      public IEnumerable<string> WheelColors{get;set;}
  }  

  @model IEnumerable<CarViewModel>
  @foreach(var car in Model)
  {
      //some View Code
      @foreach(var wheelColor in WheelColor)
      {
         <span>wheelColor</span> 
         // some View Code
      }
  }
Run Code Online (Sandbox Code Playgroud)

现在,您的视图代码在其功能方面受到很大限制,并且不会向数据库发送任何恶意查询.您的控制器可以真正控制视图的获取.你可以在那里推动轮逻辑,或者理想地在一些从动作方法调用的服务方法中.此外,您可以对操作方法进行适当的测试,并对您的系统充满信心.我希望这有帮助.

更新

案例3(动态ViewModel): 如果您对动态类型感到满意,则可以避免所有的转换和映射.只要您的视图获得所需的属性,它就会很高兴.这些来自哪里并不重要.所以代码将是:

  public class CarViewModel
  {
      public string CarName{get;set;}
      //More properties
      public IEnumerable<string> WheelColors{get;set;}
  }  

  // pass the List<CarViewModel> to the view

  @model dynamic
  @foreach(var car in Model)
  {
      //some View Code
      @foreach(var wheelColor in WheelColor)
      {
         <span>wheelColor</span> 
         // some View Code
      }
  }
Run Code Online (Sandbox Code Playgroud)

潜在的缺点/额外工作是确保您对模型上存在这些属性进行测试.

再次像前面提到的那样,这不应该被视为适合所有类型的解决方案.这些是一些选项,只有在它们有意义时才使用.


Eri*_*sch 3

这是不可能的,因为我们不知道您的模型是什么以及是否存在任何安全问题。

一般来说,安全问题不在于将模型传递给视图,而在于接收自动绑定到数据模型的帖子。如果您其中包含敏感信息,那么有人可能会制作一篇帖子来更改您不希望看到的内容。

请参阅http://odetocode.com/blogs/scott/archive/2012/03/12/complete-guide-to-mass-assignment-in-asp-net-mvc.aspx

更大的问题是,它们真的一样吗?您确定它们会保持不变吗?您确定不需要进行需要视图模型与数据模型有不同要求的更改吗?

预先完成工作并遵循良好的设计比稍后在需要时尝试修复它更容易。