【问题标题】:Version Routing in Web Api and versioned controllersWeb Api 和版本控制器中的版本路由
【发布时间】:2016-05-25 15:44:33
【问题描述】:

使用 .Net 4.5.2

我在 Web Api 中使用版本化路由。

规范要求我们定义以下路由:

/api/v1/members/test

/api/v2/members/test

以下代码在版本 1 中找到正确的方法。

 private static IEnumerable<VersionedRoute> GetRoutes(int version)
    {
        var routes = new List<VersionedRoute>();
        if (version >= 1)
        {
            var versionedRoutes = new List<VersionedRoute>
            {
                new VersionedRoute(
                    version,
                    "Test",
                    "/Members/{id}/{action}",
                    new RouteValueDictionary
                    {
                        {"controller", "Members"},
                        {"action", "Test"},
                        {"id", RouteParameter.Optional}
                    })
            };

            routes.AddRange(versionedRoutes);
        }

        if (version >= 2)
        {
            var versionedRoutes = new List<VersionedRoute>{
                new VersionedRoute(
                    version,
                    "TestV2",
                    "/Members/{id}/{action}",
                    new RouteValueDictionary
                    {
                        {"controller", "MembersV2"},
                        {"action", "Test"},
                        {"id", RouteParameter.Optional}
                    }),
            };
            routes.AddRange(versionedRoutes);
        }

        return routes;
    }

对于 v1,当我们如下定义方法时,这一切都有效

        [HttpGet]
        [ActionName("Test")]
        public HttpResponseMessage GetTest(string id)
        {
            var x = "GET: Well helleeoo";
            return new HttpResponseMessage(HttpStatusCode.Accepted) {Content =  new StringContent(x)};
        }

        [HttpPut]
        [ActionName("Test")]
        public HttpResponseMessage PutTest(string id)
        {
            var x = "PUT: Well helleeoo";
            return new HttpResponseMessage(HttpStatusCode.Accepted) { Content = new StringContent(x) };
        }

但是,正如您所见,对于 v2 路由,我想将请求定向到不同的控制器 (MembersV2),它会在其中找到 v2 方法但保持相同的路由公开。不幸的是,没有找到 MembersV2,所以当我向 api/v2/members/test 发送请求时,虽然找到了路由,但仍然调用了 Members 控制器并执行了旧的 v1 方法。

这里有什么我不明白的地方。有人可以帮忙吗?

如果我不清楚,请要求更多说明?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-web-api


    【解决方案1】:

    有多种方法可以进行 API 版本控制。您绝对不想重新发明轮子,因为它可能非常复杂。

    您可以阅读ASP.NET Web API: Using Namespaces to Version Web APIs

    ASP.NET Web API 2: Building a REST Service from Start to Finish 书的第 57 页中,Jamie Kurtz 解释了他如何修改上述代码以满足新 Web API 2 中的需求。

    我个人喜欢 Jamie Kurtz 的修改版本,并在我的一些 API 中使用它。

    【讨论】:

    • 这是在应用程序中完成的方式,因此其他方法目前不在桌面上
    • 天哪,看到 Jamie 的修改版会很方便,虽然我很欣赏这本书是版权的。
    • 同上@JeremyThompson——我意识到什至斯基特说link-only can be okay,但书的链接是另一个删除。至少在美国的合理使用应该允许对这里的建议进行很好的总结和演示,以使其成为一个有用的答案。照原样,没有那么多。 (顺便说一句,我在 this version on page 57 上没有看到它。)
    【解决方案2】:

    您在这两种情况下定义的路由都是"/Members/{id}/{action}",因此对v2/members/test 的请求与第一个v1 路由的模板匹配(因为在匹配请求时路由定义的顺序很重要)

    所以你需要做的是用明确的版本定义你的路由,如下所示:

    private static IEnumerable<VersionedRoute> GetRoutes(int version)
    {
        var routes = new List<VersionedRoute>();
        if (version >= 1)
        {
            var versionedRoutes = new List<VersionedRoute>
            {
                new VersionedRoute(
                    version,
                    "Test",
                    "v1/Members/{id}/{action}",
                    new RouteValueDictionary
                    {
                        {"controller", "Members"},
                        {"action", "Test"}
                    })
            };
    
            routes.AddRange(versionedRoutes);
        }
    
        if (version >= 2)
        {
            var versionedRoutes = new List<VersionedRoute>{
                new VersionedRoute(
                    version,
                    "TestV2",
                    "v2/Members/{id}/{action}",
                    new RouteValueDictionary
                    {
                        {"controller", "MembersV2"},
                        {"action", "Test"}
                    }),
            };
            routes.AddRange(versionedRoutes);
        }
    
        return routes;
    }
    

    【讨论】:

    • 抱歉路由应该是api/v2/members/test
    • 我更新了答案,但同样的原因仍然适用
    • 我真的不明白你想要做什么。在这种情况下,ID 用于其他用途,而不是用于版本控制]
    猜你喜欢
    • 2012-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多