【问题标题】:Does it Make Sense to have ViewModels in the Webapi?在 Webapi 中使用 ViewModel 有意义吗?
【发布时间】:2013-04-28 06:17:30
【问题描述】:

我开始学习 webapi,发现自己在做一些在 MVC 项目中有意义但在 MVC 项目中可能没有意义的事情。

通常在 MVC 项目中,我制作 ViewModel 并将其用作参数或将它们与视图一起传回。

由于 webapi 中没有视图,我想将 ViewModel 作为参数是没有意义的。

我想知道我是否应该将我的 EF 域(代码优先)作为参数并将数据注释放在这些域之上。我通常会将注释放在视图模型属性上,因为我喜欢在域上这样做。

但是,阻止我这样做的是我不是 100% 清楚我的 MVC 网站将如何工作。

MVC 站点是否只是返回简单视图,然后您使用 Jquery 调用您的 webapi,或者您是否只是调用直接调用 Webapi 将调用的相同方法的 MVC 操作方法?

如果是第二种方式,那么我宁愿再次将数据注释放在我的视图模型上,但是我将相同的注释放在 EF 域和 VM 上,这似乎是多余的。

【问题讨论】:

    标签: asp.net-mvc asp.net-web-api


    【解决方案1】:

    抛开术语不谈,绑定模型仍然有用。从技术上讲,它们不再是 ViewModel,因为您是对的,不涉及任何视图。但它们肯定仍然有用。使用它们可以让您利用模型属性上的属性,并允许您在需要时在 API 中重用它们。还请记住,如果您直接使用实体,WebAPI 将模型绑定所有按名称匹配的参数,即使您不是故意的。

    此外,实体模型是您的原始数据的表示,但用于绑定的模型是 API 请求需要满足才能成功处理请求的固定协定。在您的实现完成时,其中的值最终可能会跨越多个实体模型,并且根本不会持久化到数据存储中。

    【讨论】:

    • 是的,这是我不喜欢将注释放在 EF 本身上的原因之一。我想我应该使用 viewModel 但只是将其称为其他 DataModel?我仍然不清楚整个网站将如何运作。例如,我将有一个 Add 方法。移动设备和网站都可以添加。 MVC 站点是否也应该调用 webapi 方法?在这种情况下,这似乎是有道理的。但是,再次在移动设备中编辑案例如何调用 webapi 似乎是有意义的,但在网站上,您似乎更愿意使用 mvc 来获取已绑定的视图,然后再发回该视图。
    • 我遇到了同样的问题,我做出的决定是让我的一些网站使用 MVC 发送/检索数据并为其他网站使用 WebApi(从MVC 网站)。 WebApi 的主要好处是允许外部资产直接通过 API 使用您的数据/业务规则。如果您在同一个项目中已经有一个 MVC 站点,如果您可以直接使用 MVC,为什么还要强制它通过 WebApi 与您的域进行交互?我同意稍微不同的名称更改会使其更清晰。输入模型?请求模型?这只是术语,实际上是一回事
    • 我猜你为你的 mvc 站点创建了一个单独的项目,然后将它放在与 webapi 相同的解决方案中。我知道 webapi 可以有 mvc 控制器,但我认为这更像是向用户显示文档等关于你的 api。
    • 我不同意没有“视图”。我会将返回的 JSON 或 XML 称为视图,通常用于另一个非人类消费者。
    • >>> 此外,实体模型是原始数据的表示,但用于绑定的模型是 API 请求需要满足的固定合约
    【解决方案2】:

    如果您正在尝试构建基于 REST 的系统,那么 ViewModel 和 View 的概念可能非常有用。您可以将 Resource 的概念相当接近地映射到 ViewModel 并将表示映射到 View。

    如果您停下来想一想 MVC 网站中的视图是什么样的。它是一个 HTML 文档。包含一堆语义信息、标题、正文、部分、段落、表格等的文档。它不应该包含“样式”信息。这是网络浏览器和 CSS 的工作。当人们开始将 HTML 视为 UI 时,他们会感到困惑。它不应该是 UI,它是 UI 的内容。

    视图只是使用某种可以通过网络传输的媒体类型的视图模型内容的具体实现。该媒体类型是什么,取决于您要满足的客户。

    【讨论】:

      【解决方案3】:

      我们目前正在开发一个使用 ASP.Net MVC 和 ASP.Net Web Api 的类似项目。

      我们使用 ASP.Net MVC 来生成页面的全局结构。 然后,我们的 MVVM javascript 实现调用 web api 将返回的数据填充到客户端视图模型中。为此,我们的 api 返回与前端等待的视图模型相对应的视图模型。

      我认为您的 api 视图模型将不同于 MVC ViewModels(从 MVVM 的角度来看不是 ViewModels)。

      这也取决于您对 api 的使用。例如,对于内部使用,您并不总是需要避免显示您的域模型。因此,您将避免在 ViewModel 中映射模型并提高性能。 但是如果您需要转换模型中的某些属性,viewModel 将极大地帮助您以松散耦合的方式构建代码。

      由于 webapi 中没有视图,我想将 ViewModel 作为参数是没有意义的。

      我会说你的 api 最终被你的视图所消耗,拥有 ViewModel 是有意义的。

      MVC 站点是否只是返回 simples 视图,然后您使用 Jquery 调用您的 webapi,或者您只是调用直接调用 Webapi 将调用的相同方法的 MVC 操作方法?

      这里只是一个选择问题。您可以调用 MVC 操作来接收生成的视图(在 html 中),或者您可以调用 WebApi 来接收 JSON/XML 响应,然后将其与视图中的 javascript 代码绑定。

      【讨论】:

        【解决方案4】:

        只是补充一下其他人所说的,使用通常称为 ViewModel 的东西对于验证也很有用。您可以使用数据注释标记您的类,包括任何验证要求。在您的控制器操作中,您仍然可以使用 ModelState 来强制进行验证并通过 HttpRequestException 或仅通过 HttpResponseMessage 返回适当的消息。

        【讨论】:

          【解决方案5】:

          我在使用这个'东西'的时间很长之后的建议:

          BindingModels 用于数据绑定(mvc 或 api)

          ViewModels 用于 mvc 上的视图(您的 api 中可能有一些 mvc 页面,所以最好有一个 这个地方,这可以是文档,介绍页面,等等。如果没有视图,那么您可以拥有零个 ViewModel)这样做的一个好处是您可以在您的 Views/web.config 中拥有 ViewModels 命名空间引用,并且它不会被您的 api 资源污染。

          ResourceModel 用于 Web api 资源。在 webapi 中,嵌套资源也是树中任意位置的资源,这在 mvc 上并不常见,因此将它们命名为资源很有意义。

          如果您想接收资源,可以使用您的资源模型。记住你收到的和你发回的一样。

          如果您想为输入自定义绑定(这应该是您的默认方案),您有自己的绑定模型。

          如果您有任何 mvc 视图,出于管理目的、文档等目的,请使用您的 ViewModel。

          如果你在 mvc 上有一个表单页面,你也可以在 POST 控制器上使用你的 BindingModel。无需为 MVC 或 WEBAPI 上的帖子使用不同的模型。特别是当模型绑定器或格式化程序可以使用相同的数据注释来理解并映射到相同的绑定模型时。

          有时,您想创建一个包含资源和一些额外字段的绑定模型。继承是你的朋友。

          有时您希望创建具有多个资源和(可选地,额外字段)资源作为属性的绑定模型。

          在 MVC 世界中,您也可以使用“资源”的概念,但它不太常见。当您在同一个项目中使用 MVC 和 Web Api 时,这会派上用场。

          如果您需要任何项目(如文件夹结构、命名空间等)的更多 cmets,请告诉我。我非常乐意分享我的缺点经验。

          哦,我忘了,映射策略值得研究。我个人自己做映射,但是将这个逻辑放在一个地方是无价的。

          编辑: 非常幼稚的例子

          ContactViewModel{
          
              string Name {get;}
              string LastName {get;}
              List<Country> AvailableCountries {get;}
              Country Country {get;}
              bool IsAdmin {get;}
          
          }
          
          ContactBindingModel{
          
              string Name {get;set;}
              string LastName {get;set;}
              int Country {get;set;}
          
          }
          
          ContactResourceModel{
          
              string Name { get;set;}
              string LastName {get;set;}
              Country Country {get;set;}
              string IsAdmin {get;}
          
          }
          

          【讨论】:

          • 我做类似的事情。我有 ViewModels 用于传递回视图,并将我的请求与 FormModels 绑定,因为大多数时候我是从网页 (MVC) 中绑定一个表单,尽管我可以看到将它们称为 BindingModels 以及用于 WebAPI 之类的东西并让它们成为更普遍的命名。我的命名约定通常类似于[Controller][Action]ViewModel。所以我最终可能会得到类似PeopleEditFormModel
          • @jimutt 最近我在功能文件夹结构而不是控制器/模型/视图方面进行了大量投资和研究。等等。在我使用 [Model]Resource 获取资源之前,[Controller][Action]ViewModel 用于视图模型,[Command]BindingModel 用于绑定模型,(其中 command 是预期的操作,如 CancelOrder、CreateModel 等)通常 Command = ActionName。
          • BindingModel 是您从
            (绑定到对象)发布的内容,而 ResourceModel(或 ApiModel,如果您愿意)它是 api enpoint(s 的特定模型的数据表示)。
          • 我一直在考虑这种方法,尤其是“BindingModels”。我觉得不好,但看到你的帖子,我很高兴:)
          • 我知道这篇文章发布已经很多年了,但它对我帮助很大。这么棒的帖子可以帮助您了解不必将所有内容归为单一模型类型。
          猜你喜欢
          • 2011-10-04
          • 1970-01-01
          • 2010-11-27
          • 2017-01-08
          • 2010-12-31
          • 2015-09-14
          • 1970-01-01
          • 1970-01-01
          • 2011-11-20
          相关资源
          最近更新 更多