使用WebAPI或MVC在ASP.NET中返回JSON

Using WebAPI or MVC to return JSON in ASP.NET

我正在构建一个客户端脚本很重的ASP.NET MVC应用程序,它将使用JSON和JQuery来操作DOM。

我的理解是Web API控制器和MVC控制器都可以返回JSON。

根据我的场景,我应该使用Web API控制器还是MVC控制器?


Web API控制器可以在任何ASP.NET应用程序中创建和托管,而不仅仅是MVC应用程序。因此,创建Web API的一个明显原因是,如果您没有MVC前端(例如,由您的公司/组织托管的经典、RESTful Web服务)。

MVC控制器通常依赖于MVC框架,如果您查看默认模板以及社区和您的同事完成的大部分工作,您会注意到几乎所有MVC控制器都是在考虑视图的情况下实现的。

就我个人而言,当我打算使用view()响应时,我使用MVC控制器,并且我将对任何不依赖于特定视图的内容使用Web API。

当然,还有一些警告,但是一般来说,如果您不需要MVC的模型绑定行为,那么您的服务是以数据为中心的,而操作是以数据为中心的(例如CRUD操作),那么您可能需要"Web API控制器"而不是"模型视图控制器"。相反,如果您的操作是以视图为中心的(例如,将用户管理页面传递给用户),或者您需要MVC的模型绑定来生成"Ajax部分"(非常不可能),那么您将需要MVC控制器。

我个人使用Web API控制器来驱动基于JSON的RESTful客户机,使用MVC控制器来处理基本的浏览器路由和SPA的交付。


WebAPI用于生成API。如果您希望有人能够使用XML、JSON等形式的API,那么您可以创建一个Web API。

在您的情况下,您只需要在JSON中与客户机交谈。

即使您的网站主要是客户端脚本驱动的,您仍然会使用ASP.NET MVC控制器,对吗?而且,由于您可能已经根据实体对控制器进行了逻辑划分,因此在其中添加这些JSON服务方法是有意义的,而不是专门为Web API创建另一个类。

所以对于你的特殊情况(如果我理解正确的话),我会坚持使用控制器。


答案归结为关注点的分离、加快服务的创建以及依赖约定而不是配置。

控制器的主要职责是作为视图和模型之间的协调器工作,但是作为API的主要职责是处理数据。对于API的约定,可以很容易地执行CRUD操作。下面是CRUD操作和HTTP操作之间的映射

  • 获取:读取
  • 职位:创建
  • 放置:更新
  • 删除:删除

因此,对于API,您不必创建单独的操作,并将其属性化为HTTP操作。


在这个场景中,我建议使用WebAPI,因为它非常适合基于JavaScript请求传输这样的数据。我通常会开发我的webapi控制器,以便它们返回一个JSON友好的对象,然后我的javascript可以轻松地解析该对象。

如果您想生成一些HTML并用JavaScript调用替换页面的段,那么您唯一想要在MVC控制器上使用某个操作进行此类操作的实时位置就是。

例如:

您有一个jquery ui日期选择器,它在选择时生成一个表示所选日期事件的单选按钮列表。

在这个场景中,您可以使用WebAPI返回一些JSON,然后使用JavaScript生成必要的HTML,但通常使用JavaScript创建大量HTML是不好的做法。最好让C构建HTML,然后通过部分视图返回它,这样您就不太可能在JavaScript解析中遇到错误。更不用说它使HTML更容易编写。


我同意肖恩·威尔逊的回答,但不知道为什么,因为我有点困惑,仍然试图理解以下(可能不正确)预兆-

  • 使用WebAPI控制器将JSON数据传递给客户机,以便客户机可以处理视图操作。这个过程不需要视图,只需要对调用方法(即javascript请求)的响应,这样客户端就可以处理任何客户端操作。
  • 当需要使用数据在页面加载期间或之后操作视图时(即不适用于SPA应用程序),请使用MVC控制器。

你看,我只是不知道我在这里是如何的不正确和困惑,因为肖恩的最后一行回答说:"我使用MVC控制器来处理基本的浏览器路由和SPA的交付。"-当我假设一个RESTful客户机可能是以JSON形式接收响应的javascript方法时,我可能不完全知道它是什么。这是StackOverflow中最近的一篇文章,作为我问题的答案远程相关,所以我回答了这篇文章,而不是重复问题。


我对ApicController唯一关心的是它是基于站点的,而不是基于区域的。一个站点只能有一个apicontroller子文件夹供您命名控制器方法。在某些情况下,您可能希望在不同的区域中复制控制器名称:

域.com/api/area1/controller1/

域.com/api/area2/controller1/

我记得有一些自定义代码设置可以这样做,但默认情况下它不起作用。