ASP.NET MVC中ApiController和Controller的区别

404

我一直在尝试 ASP.NET MVC 4 beta,并且现在有两种类型的控制器:ApiControllerController

我有点困惑在什么情况下可以选择特定的控制器。

例如:如果我要返回一个视图,那么我应该使用Controller还是普通的ApiController? 我知道 WCF Web API 现在已经与 MVC 集成了。

既然现在我们可以使用这两个控制器,有人可以指出在哪些情况下选择相应的控制器吗?


33
重要提示:ASP.NET Core已经“合并”了ApiControllerController,因此如果您正在使用更新的.NET版本,则无需再担心ApiController了 - https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-web-api - Simon_Weaver
4
我很高兴他们这样做了!顺便说一下,我早就预测过这件事情了。http://prideparrot.com/blog/archive/2012/10/asp_net_mvc_vs_webapi - VJAI
2
"Mark和Ted是好朋友。他们通常在晚餐桌上进行有趣的讨论...大多数都是技术方面的!" 没有人会期望高度技术化的幽默感。 ;^) - ruffin
8个回答

402
使用Controller来渲染您的普通视图。ApiController操作仅返回已序列化并发送到客户端的数据。 这是链接 如果您已经使用过ASP.NET MVC,那么您对控制器已经很熟悉了。它们在Web API中的工作方式类似,但是Web API中的控制器源自ApiController类而不是Controller类。您将注意到的第一个重要区别是,Web API控制器上的操作不返回视图,而是返回数据。
ApiControllers专门用于返回数据。例如,它们负责透明地将数据序列化为客户端请求的格式。此外,默认情况下,它们遵循不同的路由方案(例如:将URL映射到操作),按照约定提供RESTful API。
您可能可以使用控制器代替ApiController进行任何操作,并进行一些手动编码。最终,两个控制器都建立在ASP.NET基础之上。但是,如今具有RESTful API是如此常见的要求,因此创建了WebAPI以简化实现此类API的过程。
非常简单来决定使用哪种:如果您正在编写基于HTML的Web / Internet / Intranet应用程序 - 可能偶尔会在此处和那里返回json的AJAX调用 - 请坚持使用MVC / Controller。如果要为系统提供数据驱动的/ RESTful接口,请使用WebAPI。当然,您可以结合使用两者,例如允许ApiController处理来自MVC页面的AJAX调用。
举个实际例子:我目前正在使用一个ERP系统,该系统为其实体提供RESTful API。对于此API,WebAPI是一个很好的选择。同时,ERP系统提供高度AJAX-化的Web应用程序,可用于为RESTful API创建查询。Web应用程序本身可以作为MVC应用程序实现,利用WebAPI获取元数据等。

10
注意:由于您的数据将通过网络发送,它将如何被格式化?ApiController返回的数据格式是由内容协商和GlobalConfiguration.Configuration.Formatters决定的... 链接:http://blogs.msdn.com/b/kiranchalla/archive/2012/02/25/content-negotiation-in-asp-net-mvc4-web-api-beta-part-1.aspx - Tim Lovell-Smith
1
Web API 是一个常见的平台,可以用于网站、移动应用等。我们是否可以使用类库代替 Web API? - Imad Alazani
感谢@TimLovell-Smith的留言,因为对我来说,安德烈并没有回答这个问题:作为控制器也可以返回数据,这并不能解释为什么ApiController存在并且有用。 - JYL
2
@JYL,我增补了我的回答以提供更详细的信息。 - Andre Loker
2
当你说“按照惯例提供RESTful API”时,我并没有真正理解。它是如何提供RESTful API的?它不取决于从API返回什么数据吗?控制器中没有任何东西强制(甚至促进)API成为RESTful。 - Nawaz
显示剩余7条评论

211

你更喜欢编写和维护哪个?

ASP.NET MVC

public class TweetsController : Controller {
  // GET: /Tweets/
  [HttpGet]
  public ActionResult Index() {
    return Json(Twitter.GetTweets(), JsonRequestBehavior.AllowGet);
  }
}

ASP.NET Web API

public class TweetsController : ApiController {
  // GET: /Api/Tweets/
  public List<Tweet> Get() {
    return Twitter.GetTweets();
  }
}

8
这个观点很有道理,但ApiController不仅仅是JSON序列化。它还负责查看请求并在接受类型为XML时返回XML。 - Jake Almer
14
如果您使用ASP.NET Core,所有控制器都派生自Controller类。 - Tân
4
这些似乎是旧的例子,现在我们不必再担心 ApiController,只需使用 : Controller 即可。您希望我也添加一个新的 .NET Core 控制器示例。 - Ashish Kamble
@AshishKamble,现在使用ControllerBase而不是ApiController。 - Vladimir Shiyanov
1
说实话,我更喜欢Json()版本。它更清晰明确。我不喜欢在尝试弄清楚我的代码如何响应请求时出现大量黑魔法。 - Jez

34

我喜欢 ASP.NET Core 的 MVC6 将这两种模式合并,因为我经常需要同时支持两个世界。虽然你可以调整任何标准的 MVC Controller(和/或开发自己的 ActionResult 类)来像 ApiController 一样行事和表现,但是这很难维护和测试:除此之外,控制器方法返回混合了原始序列化数据或 IHttpActionResult 数据的 ActionResult 可以让开发人员感到非常困惑,特别是如果你不是在独自工作,还需要与其他开发人员共同处理这种混合方法。

到目前为止,我发现在 ASP.NET 非 Core 网络应用程序中最好的技术是将 Web API 包导入(并正确配置)到基于 MVC 的 Web 应用程序中,这样我就可以拥有两全其美的优点:视图使用 Controllers,数据使用 ApiControllers

要做到这一点,您需要执行以下操作:

  • 使用 NuGet 安装以下 Web API 包: Microsoft.AspNet.WebApi.CoreMicrosoft.AspNet.WebApi.WebHost
  • 向您的 /Controllers/ 文件夹添加一个或多个 ApiControllers。
  • 向您的 /App_Config/ 文件夹添加以下 WebApiConfig.cs 文件:

using System.Web.Http;

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

最后,您需要将上述类注册到您的Startup类中(根据您是否使用OWIN Startup模板,可以是Startup.csGlobal.asax.cs)。

Startup.cs

 public void Configuration(IAppBuilder app)
 {
    // Register Web API routing support before anything else
    GlobalConfiguration.Configure(WebApiConfig.Register);

    // The rest of your file goes there
    // ...
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    ConfigureAuth(app);
    // ...
}

全局.asax.cs

protected void Application_Start()
{
    // Register Web API routing support before anything else
    GlobalConfiguration.Configure(WebApiConfig.Register);

    // The rest of your file goes there
    // ...
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
    // ...
}

这种方法及其利弊在我博客上写的这篇文章中有进一步解释。


1
好事情。但是这个功能已经在VS2015中内置了。如果您创建WebAPI ASP.NET项目,它将自动为您执行所有样板代码。 - suomi-dev
@Darkseal,您能否详细说明一下“维护和测试可能非常困难”?(我已经阅读了您的博客文章) 我使用过WebAPI2,并且我喜欢它的工作方式。但是,除了将其“通常的做法”之外,我无法找到“真正的巨大好处”。使用经典的MVC控制器返回“手动”序列化字符串足够简单。添加一个json / xml开关与http Accept动词并不需要太多。所有这些都可以包装成一个不错的实用方法。谢谢。 - ValGe
2
@ValGe,可以看一下@manish-jain上面的回答。简而言之,一个返回Json序列化字符串并包装在ActionResult中的Controller肯定比一个可以直接返回[Serializable]项目列表的ApiController更难测试和维护。任何测试方法都会更容易编写,因为您不必每次手动反序列化:对于ASP.NET或其他框架的几乎任何系统集成任务也是如此。Controllers很棒,但至少在.NET Framework 4.x中,ApiControllers更适合RESTful任务。 - Darkseal

11

简要回答:

如果你想返回一个视图,你应该在“Controller”中操作。

普通控制器 - ASP.NET MVC:如果你是在ASP.net Web应用程序中,你要处理普通的“Controller”。你可以创建控制器操作并返回Views()。

ApiController控制器:当你开发ASP.net REST API时,你要创建ApiControllers。你不能返回视图(虽然你可以返回Json/Data来代替HTML字符串)。这些API被认为是后端,它们的功能是调用返回数据而不是视图。

更多细节请点击这里


1
主要的区别在于:Web API 是为任何客户端、任何设备提供服务的,而 MVC 控制器只为其客户端提供服务。这是因为它是 MVC 平台。

1
每个Web API中的方法都会返回数据(JSON),而不需要序列化。
然而,为了在MVC控制器中返回JSON数据,我们将返回的Action Result类型设置为JsonResult,并调用我们对象上的Json方法,以确保它被打包成JSON。

0

enter image description here

如果您在最新的框架4.7.2中创建一个新的Web应用程序,那么它们两个都将默认配置,并且您可以在此基础上构建应用程序。

enter image description here


-3

在 Asp.net Core 3+ 版本中

Controller: 如果想要返回任何与 IActionResult 和 Data 相关的内容,请使用 Controllercontroller

ApiController: 用作 API 控制器中的属性/注释。继承 ControllerBase 类

ControllerBase: 如果只想返回数据,请使用 ControllerBase 类


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接