Reputation: 1665
In my ASP.NET Core project I'm using aspnet-api-versioning like so:
[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)
{
...
}
}
So the request is sent to: GET /api/v1/users
.
When adding another version of this action I would just add the attribute MapToApiVersion("2.0")
so it would be GET /api/v2/users
.
That's all fine.
However in a view I call this action with ajax like so:
$.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
};
}));
}
});
This calls the endpoint:/User/GetUsers?version=1?searchString={searchString}&allOrganizations=true
So it appends the version as a query parameter instead of route parameter.
If I don't add the new {version = 1}
it's the same just without the 'version' query parameter.
I've also tried using @Url.RouteUrl("Get_Users", new {version =1})
and naming the action with [HttpGet("Get_Users"), MapToApiVersion("1.0")]
but that just appends the query parameters to the current url.
However if I change the Controllers route attribute from [Route("api/v{version:apiVersion}/users")]
to [Route("api/users")]
and ommit the version parameter, the ajax call works fine.
So is there any way to use IUrlHelper
(or some other way) to get the correct route to a versioned action besides hardcoding the url string? Or am I doing versioning wrong in some way?
I may just be complicating here, but I still think this should work, no?
Upvotes: 4
Views: 2238
Reputation: 4368
Unfortunately, IUrlHelper is not API version-aware. I would recommend naming routes you need to resolve with a versioned name (e.g. [HttpGet(Name = "GetUsersV1")]
) and then use Url.Link( "GetByUsersV1", new { version = "1.0" } )
.
Upvotes: 2
Reputation: 1346
The (got me annoyed) solution to this is to pass the exact API version
value as a string value instead of an integer as you did. So in your razor snippet the IUrlHelper
instance should be called like this:
url: '@Url.Action("GetUsers", "User", new { version = "1.0" })' ...
Please notice that the version is explicitly 1.0 which correctly (in terms of syntax like MAJOR.MINOR) matches the one you have specified in the attribute like [ApiVersion("1.0")]
.
Upvotes: 2
Reputation: 24515
I appreciate this answer is not .net core specific and may not answer you question, but consider creating api controllers with the version in the name of the controller
e.g. V1Controller, V2Controller so the Urls /api/v1/GetUsers, /api/v2/GetUsers this handles versioning and keeps the code discreet between versions and reduces any method name conflicts.
Upvotes: 2