C# 无法调用版本化的API控制器方法

C# 无法调用版本化的API控制器方法,c#,asp.net-mvc-4,asp.net-web-api,versioning,C#,Asp.net Mvc 4,Asp.net Web Api,Versioning,我有一个版本化的webapi项目,由4个版本化的控制器组成 问题背景: 目前,我有一个自定义路由方法类-显示在底部,用于根据URL中传递的查询“版本”字符串参数选择要选择的控制器-例如,访问V2(版本2)“ProductV2Controller”并获取URL将包含的所有产品对象: http://localhost:1487/api/product/?v=2/ 我的路线定义如下所示: config.Routes.MapHttpRoute( name: "NewProduct

我有一个版本化的webapi项目,由4个版本化的控制器组成

问题背景: 目前,我有一个自定义路由方法类-显示在底部,用于根据URL中传递的查询“版本”字符串参数选择要选择的控制器-例如,访问V2(版本2)“ProductV2Controller”并获取URL将包含的所有产品对象:

http://localhost:1487/api/product/?v=2/
我的路线定义如下所示:

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

        //*****Custom route selector*****
       config.Services.Replace(typeof(IHttpControllerSelector), new Selector.ControllerSelector(config));
它在哪里工作: 如果我在名为“ProductController”的简单无版本控制器中调用“GetProductByName”方法,这很好,并基于传递的名称返回DTO对象。这是通过以下查询字符串实现的:

http://localhost:1487/api/product/Name=Table
问题: 然后,当我尝试对版本化控制器执行相同操作时,再次使用查询字符串指定控制器版本,并使用以下URL使用具有指定“Name”参数的查询字符串:

http://localhost:1487/api/product/?v=2/?Name=Table
应该命中的方法:

public Product GetProductByName(string name)
    {
        return V2Ops.GetProductByName(name);
    }
这将被忽略并返回简单的“ProductController”“GET”all方法

这就是我的“ControllerSelector”类将所选版本控制器URL返回到路由的方式:

productV2/?Name=Table
这在我看来似乎是正确的,这是选择了正确的控制器,但我不明白为什么它不会路由到“GetProductByName”方法

更新-添加了“ControllerSelector”类:
看来我已经解决了这个问题

这是一个简单的例子,代码是正确的,但URL不是:

我之前使用的方法,即使用两个查询字符串的方法是错误的:

http://localhost:1487/api/product/?v=2/?Name=Table
这是正确的格式。一个查询:

http://localhost:1487/api/product/?v=2&Name=Table

现在这个功能非常好。

看起来我已经成功地对它进行了排序

这是一个简单的例子,代码是正确的,但URL不是:

我之前使用的方法,即使用两个查询字符串的方法是错误的:

http://localhost:1487/api/product/?v=2/?Name=Table
这是正确的格式。一个查询:

http://localhost:1487/api/product/?v=2&Name=Table

这现在可以完美地工作。

您尝试使用的URL中有两个单独的查询字符串;这不是HTTP URL的合法语法。在自定义路由逻辑中获得的查询参数几乎肯定是错误的。特别是,我强烈怀疑您在任何地方都没有看到名为“Name”的参数,因为它没有正确格式化为“second”参数。这就解释了为什么路由逻辑无法确定将请求发送到哪里

您应该将所有参数滚动到一个查询字符串中,并从中解析它们;如果需要将部分(而不是全部)发送到最终目标控制器,则始终可以使用剩余参数重新生成新的查询字符串。e、 g:

Incoming: http://localhost:1487/api/product/?v=2&Name=Table
Outgoing: http://localhost:1487/api/productV2/?Name=Table

或者您需要的任何内容。

您尝试使用的URL中有两个单独的查询字符串;这不是HTTP URL的合法语法。在自定义路由逻辑中获得的查询参数几乎肯定是错误的。特别是,我强烈怀疑您在任何地方都没有看到名为“Name”的参数,因为它没有正确格式化为“second”参数。这就解释了为什么路由逻辑无法确定将请求发送到哪里

您应该将所有参数滚动到一个查询字符串中,并从中解析它们;如果需要将部分(而不是全部)发送到最终目标控制器,则始终可以使用剩余参数重新生成新的查询字符串。e、 g:

Incoming: http://localhost:1487/api/product/?v=2&Name=Table
Outgoing: http://localhost:1487/api/productV2/?Name=Table

或者你需要的任何东西。

我认为拥有两个查询字符串都是不合法的,你的查询字符串的解析方式几乎肯定与你想象的不同。另外,查看您的自定义
IHttpControllerSelector
的部分内容也会有所帮助,因为所有工作都是在这里完成的。@MichaelEdenfield感谢您的回答。我设法解决了这个问题,但你提到两个查询字符串是非法的,这让我走上了正确的道路。如果你把它作为你的答案放在下面,我会把它设置为正确答案。我认为拥有两个查询字符串是不合法的,你的查询字符串的解析方式几乎肯定与你想象的不同。另外,查看您的自定义
IHttpControllerSelector
的部分内容也会有所帮助,因为所有工作都是在这里完成的。@MichaelEdenfield感谢您的回答。我设法解决了这个问题,但你提到两个查询字符串是非法的,这让我走上了正确的道路。如果你把这个作为你下面的答案,我会把它设置为正确答案。