Skip to content

The "more specific route" priority rule is not honored #797

Closed
@gdurandrexel

Description

@gdurandrexel

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.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions