在Webapi中使用ViewModel是否有意义?


69

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

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

由于webapi中没有视图,因此我认为将ViewModel作为参数没有任何意义。

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

但是,阻止我执行此操作的原因是我不是100%清楚我的MVC网站如何工作。

MVC站点只是回吐简单视图,然后使用Jquery调用您的webapi还是仅调用MVC操作方法而直接调用与Webapi相同的方法?

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

Answers:


36

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

此外,实体模型是原始数据的表示形式,但是用于绑定的模型是API请求成功满足请求所需的固定合同。值在实现完成时最终可能会跨越多个实体模型,而根本不会持久保存到数据存储中。


是的,这就是为什么我不喜欢将注释放在EF本身上的原因之一。我想我应该使用viewModel,但只是将其称为其他DataModel?我仍然不清楚整个网站将如何运作。例如,我将有一个Add方法。移动设备和网站都可以添加。MVC站点也应该调用webapi方法吗?在这种情况下,这似乎很有意义。但是,再次在移动设备中使用Edit Case调用webapi似乎很有意义,但是在站点上,您似乎更希望使用mvc来获取绑定的视图,然后再发布回该视图。
chobo2

我遇到了同样的问题,我的决定是让我的某些站点使用MVC发送/检索数据,而对其他站点使用WebApi(从MVC站点发送)是没有意义的。WebApi的主要好处是允许外部资产直接通过API使用您的数据/业务规则。如果您已经在同一项目中拥有一个MVC站点,那么如果可以直接使用MVC,为什么要强制它通过WebApi与您的域进行交互?我同意略有不同的名称更改会使其更清晰。InputModel?RequestModel?这只是术语,实际上是同一回事
Nick Albrecht

我猜您为mvc网站创建了一个单独的项目,然后将其与webapi放在相同的解决方案中。我知道webapi可以具有mvc控制器,但我认为这更多是为了向用户显示文档以及与您有关的api。
chobo2

2
我不同意没有“视图”。我将返回的JSON或XML称为视图,通常用于其他非人类使用者。
Wix 2015年

2
>>>另外,实体模型是原始数据的表示形式,但是用于进行绑定的模型是API请求满足以下条件的固定合同:<< IMO,这是最有力的论点
david.barkhuizen

41

我的建议是在长时间使用此“事物”后进行的

数据绑定的BindingModels(mvc或api)

用于在mvc上进行查看的ViewModels(您的api中可能包含一些mvc页面,因此最好在其中放置一个地方,可以是文档,简介页等。如果没有视图,则可以有零个ViewModels)这样做的好处是,您可以在Views / web.config中具有ViewModels命名空间引用,并且不会被api资源污染。

Web API资源的ResourceModel。在webapi中,嵌套资源也是在树中任何地方都可以访问的资源,这在mvc上并不常见,因此给资源命名很有意义。

如果要接收资源,则可以使用资源模型。记住,您收到的与您寄回的一样。

如果要为输入使用自定义绑定(这应该是默认方案),则可以使用绑定模型。

如果您出于管理目的,文档目的而拥有任何mvc视图,请使用ViewModels。

如果您在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;}

}

1
我做类似的事情。我有ViewModels可以传回视图,并将请求绑定到FormModels,因为大多数时候我都绑定网页(MVC)上的表单,尽管我可以看到像WebAPI这样的东西也将它们称为BindingModels并让它们成为更普遍地命名。我的命名惯例通常是[Controller][Action]ViewModel。所以我最终可能会遇到这样的情况PeopleEditFormModel
Nick Albrecht

1
@jimutt最近,我在功能文件夹结构而不是控制器/模型/视图上进行了大量投资和研究。在[Model]Resource用于资源,[Controller][Action]ViewModel视图[Command]BindingModel模型和绑定模型之前(其中命令是预期的操作,如CancelOrder,CreateModel等),通常用于Command = ActionName。
Bart Calixto

2
BindingModel是您从<form post>中发布的内容(绑定到对象),而ResourceModel(如果需要,则为ApiModel)则是特定的api enpoint模型的数据表示形式。
Bart Calixto

1
我一直在考虑这种方法,尤其是“ BindingModels”已有一段时间了。我以为这不好,但是一旦看到您的帖子,它就让我非常开心:)
Arad

1
我知道自发布以来已经有很多年了,但这对我有很大帮助。如此出色的文章可以帮助您了解,您不必将所有内容都归纳为一个模型类型。
ChronoZZ

8

如果您尝试构建基于REST的系统,则ViewModel和View的概念可能非常有用。您可以相当紧密地将Resource的概念映射到ViewModel并将表示形式映射到View。

如果您停下来思考一下MVC网站中的视图是什么样子。这是一个HTML文档。包含大量语义信息,标题,正文,节,段落,表等的文档。不应包含“样式”信息。这就是Web浏览器和CSS的工作。人们开始将HTML视为UI时会感到困惑。它不应该是UI,它是UI的内容。

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


3

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

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

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

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

由于webapi中没有视图,因此我认为将ViewModel作为参数没有任何意义。

我要说的是,您的api最终会被视图占用,拥有ViewModel才有意义。

MVC站点只是回吐简单视图,然后使用Jquery调用您的webapi还是仅调用MVC操作方法而直接调用与Webapi相同的方法?

这只是选择的问题。您可以调用MVC操作来接收生成的视图(以html格式),也可以调用WebApi来接收JSON / XML响应,然后将它们与视图中的javascript代码绑定。


2

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.