【问题标题】:Versioning Web API actions in ASP.NET MVC 4ASP.NET MVC 4 中的版本控制 Web API 操作
【发布时间】:2012-12-21 01:02:18
【问题描述】:

我有一个 ASP.NET MVC 4 应用程序。我想将新的 Web API 功能用于学习目的。我想学习如何公开相同的端点,但提供不同的版本。换句话说,我想公开如下端点:

http://mysite/1.0/Products/1
http://mysite/2.0/Products/1

为了做到这一点,我在默认的“Controllers”目录中添加了一个“Api”目录。在“Api”目录中,我还有另外两个目录:“Version1-0”和“Version2-0”。这些目录中的每一个都有一个名为“ProductsController”的 ApiController。

我尝试通过在我的 WebApiConfig.cs 文件中添加以下路由定义来公开端点:

config.Routes.MapHttpRoute(
  name: "1-0Api",
  routeTemplate: "api/1.0/{controller}/{id}",
  defaults: new { id = RouteParameter.Optional }
);

不幸的是,我不知道如何通过上面列出的 URL 公开操作。我究竟做错了什么?谢谢!

【问题讨论】:

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


    【解决方案1】:

    您可能会遇到问题,因为控制器具有相同的名称。控制器命名空间或它所在的文件夹对 WebAPI 来说根本不重要,只有名称才重要。我能想到的最简单的事情是重命名您的控制器 ProductsV1Controller 和 ProductsV2Controller 并设置两条路由指向您的控制器:

    config.Routes.MapHttpRoute(
        name: "1-0Api",
        routeTemplate: "api/1.0/Products/{id}",
        defaults: new { controller = "ProductsV1", id = RouteParameter.Optional }
    );
    config.Routes.MapHttpRoute(
        name: "2-0Api",
        routeTemplate: "api/2.0/Products/{id}",
        defaults: new { controller = "ProductsV2", id = RouteParameter.Optional }
    );
    

    当然,如果您想要以这种方式公开多个控制器,这会变得很混乱。让我看看我能不能想出更好的东西给你。

    【讨论】:

    • 目前,我只有 1 个控制器 (ProductsV1Controller),无法访问该端点。我究竟做错了什么?该项目没有其他变化。我真的开始了一个新的 ASP.NET MVC 4 项目并想添加一个版本控制的控制器。
    • 有几件事可能是错误的。您的控制器可能不是公共类,控制器可能不是从 ApiController 或其他东西派生的。您从本地计算机上的服务器返回的响应是什么?
    • 我的控制器是一个公共类。控制器确实派生自 ApiContoller。在我的本地机器上,我收到 404。这是最奇怪的事情。
    • 响应正文中有内​​容吗? WebAPI 应该添加有关出了什么问题的信息,
    • @YoussefMoussaoui 你有没有想过更好的方法来做到这一点?或者完全不同的方式来实现 API 的版本控制?我想使用 HTTP Accept 标头,如 barelyenough.org/blog/2008/05/versioning-rest-web-services 中所述,但我必须支持一些旧的 Flex 客户端东西,这些东西几乎无法修改 HTTP 标头:(
    【解决方案2】:

    Sebastiaan Dammann 在他的博客中描述了他如何通过编写自己的 IHttpControllerSelector 实现和支持接口来进行 Web API 版本控制。

    http://damsteen.nl/blog/implementing-versioning-in-asp.net-web-api

    他也把代码放到了github上

    https://github.com/Sebazzz/SDammann.WebApi.Versioning

    并为我们将其打包在 NuGet 中! :)

    https://nuget.org/packages/SDammann.WebApi.Versioning

    虽然实现 IHttpControllerSelector 肯定是(恕我直言)进行 Web API 版本控制的正确方法,我认为如果他包含基于 HTTP Accept 标头的版本功能将是理想的 (见http://barelyenough.org/blog/2008/05/versioning-rest-web-services/)。

    很遗憾,我的客户端无法使用 Accept 标头,因此他的 RouteVersionedControllerSelector 非常适合我。

    编辑:不知道我是怎么错过的,但确实有一个AcceptHeaderVersionedControllerSelector 可以用来以理想的方式进行版本控制。我目前正在一个新项目中使用它,但它仍然有some drawbacks

    【讨论】:

      【解决方案3】:

      您是否仍然定义了默认的 Web API 路由并且它您的自定义路由之前?这将导致您的方案失败。以下路线定义(注意顺序)对我有用。

      public static void Register(HttpConfiguration config) {
          config.Routes.MapHttpRoute(
              name: "1-0Api",
              routeTemplate: "api/1.0/{controller}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
      
          config.Routes.MapHttpRoute(
              name: "DefaultApi",
              routeTemplate: "api/{controller}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );
      }
      

      【讨论】:

        【解决方案4】:

        【讨论】:

          【解决方案5】:

          如果我们采用您的第一种方法,那么它有助于路由并允许我们获取 V1、V2 的数据......但现在我们已经为一个控制器提供了 v1 和 v2 的示例,因此路由代码将如下所示下面:

          config.Routes.MapHttpRoute(
              name: "1-0Api",
              routeTemplate: "tables/v1/Products",
              defaults: new { controller = "ProductsV1", id = RouteParameter.Optional }
          );
          config.Routes.MapHttpRoute(
              name: "2-0Api",
              routeTemplate: "tables/v2/Products",
              defaults: new { controller = "ProductsV2", id = RouteParameter.Optional }
          );
          

          但是我们有 20 多个控制器和多个版本,那么如何使其通用。

          【讨论】:

            猜你喜欢
            • 2019-06-06
            • 2017-03-18
            • 2018-02-21
            • 1970-01-01
            • 1970-01-01
            • 2012-09-04
            • 1970-01-01
            • 2011-08-21
            • 1970-01-01
            相关资源
            最近更新 更多