使用IUrlHelper生成版本化API动作的URL

时间:2017-01-17 15:19:02

标签: c# routing asp.net-core asp.net-core-mvc api-versioning

在我的ASP.NET核心项目中,我正在使用aspnet-api-versioning,如下所示:

[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/users")]
[Authorize]
public class UserController : Controller
{

  [HttpGet, MapToApiVersion("1.0")]
  public async Task<IActionResult> GetUsers([FromQuery] string searchString, [FromQuery] bool allOrganizations = false)
  {
   ...
  }

}    

因此请求将发送至:GET /api/v1/users

添加此操作的其他版本时,我只需添加属性MapToApiVersion("2.0"),使其为GET /api/v2/users。 这一切都很好。

但是在视图中我用ajax这样调用这个动作:

$.ajax({
url: '@Url.Action("GetUsers", "User", new{version = 1})' + "?searchString=" + $("#user-search").val() + "&allOrganizations=true",
type: "GET",
success: function(data) {
response($.map(data,
function(obj) {
return {
        //some mapping
       };
 }));
}
});

这会调用端点:/User/GetUsers?version=1?searchString={searchString}&allOrganizations=true

因此它将版本作为查询参数而不是路由参数附加。

如果我不添加new {version = 1},那么只是没有'version'查询参数。

我还尝试使用@Url.RouteUrl("Get_Users", new {version =1})并将操作命名为[HttpGet("Get_Users"), MapToApiVersion("1.0")],但只是将查询参数附加到当前网址。

但是,如果我将控制器路由属性从[Route("api/v{version:apiVersion}/users")]更改为[Route("api/users")]并省略version参数,则ajax调用可以正常工作。

除了硬编码url字符串之外,还有什么方法可以使用IUrlHelper(或其他方式)获取版本化操作的正确路由?或者我在某种程度上做版本错误?

我可能只是在这里变得复杂,但我仍然认为这应该有效,不是吗?

3 个答案:

答案 0 :(得分:1)

我很欣赏这个答案不是.net核心特定的,可能不会回答你的问题,但考虑用控制器名称中的版本创建api控制器

e.g。 V1Controller,V2Controller,因此Urls / api / v1 / GetUsers,/ api / v2 / GetUsers可以处理版本控制并在版本之间保持代码谨慎,并减少任何方法名称冲突。

答案 1 :(得分:1)

不幸的是, IUrlHelper 不支持API版本。我建议使用版本化名称(例如[HttpGet(Name = "GetUsersV1")])命名您需要解析的路线,然后使用Url.Link( "GetByUsersV1", new { version = 1 } )

答案 2 :(得分:0)

(让我烦恼)的解决方案是将确切的API version值作为字符串值而不是像整数那样传递。因此,在您的剃须刀摘录中,IUrlHelper实例应按以下方式调用:

url: '@Url.Action("GetUsers", "User", new { version = "1.0" })' ...

请注意,该版本明确为1.0,该版本正确地(如MAJOR.MINOR这样的语法)与您在属性中指定的版本[ApiVersion("1.0")]相匹配。