question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

The "more specific route" priority rule is not honored

See original GitHub issue

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.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
gdurandrexelcommented, Jan 3, 2022

Hello, here is a reproducer: ApiVersionMoreSpecificRoute.zip

Thx for the tip on the custom convention. Note that in my case I had to ensure the controller didn’t have the ApiVersionNeutral attribute:

public bool Apply(IControllerConventionBuilder controller, ControllerModel controllerModel)
{
	if (!controllerModel.Attributes.OfType<ApiVersionNeutralAttribute>().Any())
	{
		// set the supported versions
		controller.HasApiVersions(_supportedVersions);

		// assign the obsolete version to the obsolete methods
		foreach (ActionModel action in controllerModel.Actions)
		{
			if (action.Attributes.OfType<ObsoleteAttribute>().Any())
			{
				controller.Action(action.ActionMethod).MapToApiVersion(_obsoleteVersion);
			}
		}

		return true;
	}

	return false;
}
0reactions
gdurandrexelcommented, Jan 4, 2022

Thanks. I will use solution 1 as it seems it makes sense here anyway.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Windows [10] network route precedence rules other than ...
1 Answer. Route selection on windows, involves: Finding the most specific routes to the destination. Selecting the most specific route with the ...
Read more >
Configure route tables
Rules and considerations. You can add a route to your route tables that is more specific than the local route. The destination must...
Read more >
Routing priority issue - MikroTik
Because in this release, the routing-mark assigned by a mangle rule cannot be superseded using a routing rule. So the rules are not...
Read more >
How can I set the metric of a manually added route on ...
I am using the following command to add a route, but the metric isn't working the way I want it to. I want...
Read more >
static route overrides PBR on cisco6509
PBR static routes have priority over static routes in the routing table. If the packet does not match a PBR static route, the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found