71

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

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

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

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

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

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

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

4

5 回答 5

46

在长时间使用这些“东西”之后,我的建议是:

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

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

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

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

如果你想要一个自定义的输入绑定(这应该是你的默认场景)你有你的绑定模型。

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

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

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

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

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

如果您需要对任何项目(如文件夹结构、命名空间等)进一步评论,请告诉我。我非常乐意分享我的利弊经验。

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

编辑:非常天真的例子

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

}
于 2014-08-06T22:35:01.687 回答
37

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

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

于 2013-05-03T19:08:21.733 回答
8

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

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

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

于 2013-05-03T19:55:44.773 回答
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 站点是否只是返回简单视图,然后您使用 Jquery 调用您的 webapi,或者您只是调用直接调用 Webapi 将调用的相同方法的 MVC 操作方法?

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

于 2013-05-04T10:34:02.843 回答
2

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

于 2013-06-11T04:00:36.367 回答