Closed
Description
I have a controller that supports 2 versions (Latest and Obsolete), and this controller contains these routes:
- sites/{siteId} with [MapToApiVersion(ApiVersions.Latest)]
- sites/contracts with no version qualifier (should be available for both Latest and Obsolete).
If I call sites/contracts with version Latest (from header) I expect this route to be called, but it is actually sites/{siteId}.
I know I can disambiguate with siteId:int but I don't see any reason why the "more specific route" wouldn't apply here.
My config (as is, in case I made some mistake):
Basically all the controllers support Latest and Obsolete versions, and [Obsolete] methods are mapped to the Obsolete version.
services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
ApiVersion obsoleteVersion = ApiVersion.Parse(ApiVersions.Obsolete);
options.DefaultApiVersion = obsoleteVersion;
options.ApiVersionReader = new HeaderApiVersionReader("X-Api-Version");
// configure every ApiController that supports versioning
ApiVersion[] supportedVersions = new[] { obsoleteVersion, ApiVersion.Parse(ApiVersions.Latest) };
foreach (Type controller in Assembly.GetExecutingAssembly().GetTypes()
.Where(_ => _.GetCustomAttribute<ApiControllerAttribute>(true) != null && _.GetCustomAttribute<ApiVersionNeutralAttribute>(true) == null))
{
IControllerConventionBuilder controllerConventions = options.Conventions.Controller(controller);
// set the supported versions
controllerConventions.HasApiVersions(supportedVersions);
// assign the obsolete version to the obsolete methods
foreach (MethodInfo method in controller.GetMethods()
.Where(_ => _.GetCustomAttribute<ObsoleteAttribute>(true) != null))
{
controllerConventions.Action(method).MapToApiVersion(obsoleteVersion);
}
}
});
And the controller:
[Route("api/prouser/sites")]
public class SiteController : ProUserControllerBase
{
...
[HttpGet("{siteId}")]
[MapToApiVersion(ApiVersions.Latest)]
public async Task<SiteDto> GetSite([FromRoute] SiteId siteId)
...
[HttpGet("contracts")]
public async Task<IEnumerable<ContractsDto>> GetContracts()
Note that setting Latest as the default version (options.DefaultApiVersion = ApiVersion.Parse(ApiVersions.Latest);
) produces the same result.