在ASP.NET MVC 4中对Web API操作进行版本控制

时间:2012-12-21 01:02:19

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

我有一个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公开操作。我究竟做错了什么?谢谢!

5 个答案:

答案 0 :(得分:7)

您可能遇到问题,因为控制器具有相同的名称。控制器命名空间或它所在的文件夹对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 :(得分:5)

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肯定是(imho)进行Web API版本控制的正确方法,但我认为如果他能够基于HTTP Accept标题包含版本,那将是理想的选择(见http://barelyenough.org/blog/2008/05/versioning-rest-web-services/)。

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

编辑:不确定我是如何错过的,但确实有一个AcceptHeaderVersionedControllerSelector可用于对理想方式进行版本控制。我目前正在一个新项目上使用它,但它仍然有some drawbacks

答案 2 :(得分:1)

您是否仍然定义了默认的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 }
    );
}

答案 3 :(得分:1)

答案 4 :(得分:0)

如果我们要进行第一种方法,那么它有助于路由并允许我们获取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个控制器和多个版本,然后如何使它通用。