Closed ilcos91 closed 1 month ago
Thanks for the info and repro setup; it's useful. Taking what you've provided, I added the DeliveriesController
to the OpenAPI example project and everything works as expected. The exact code I dropped in was:
[Route( "api/[controller]" )]
[ApiController]
[ApiVersion( 1 )]
[ApiVersion( 2 )]
[ApiVersion( 3 )]
public class DeliveriesController : ControllerBase
{
[HttpPost]
[Obsolete( "Please use the latest version of this service" )]
[MapToApiVersion( 1 )]
public IActionResult GetDeliveries(
[FromHeader( Name = "ContextOwner" )] string contextOwnerHeaderString,
[FromHeader( Name = "Company" )] string companyHeaderString,
[FromHeader( Name = "SourceDeviceType" )] string sourceDeviceTypeHeaderString) => Ok();
[HttpPost]
[MapToApiVersion( 2 )]
public IActionResult GetDeliveries_V2(
[FromHeader( Name = "ContextOwner" )] string contextOwnerHeaderString,
[FromHeader( Name = "Company" )] string companyHeaderString,
[Required][MinLength( 2 )][FromHeader( Name = "LanguageCode" )] string language) => Ok();
}
This contains a few very minor tweaks to just get it running.
The exception stack trace shows:
...
Microsoft.AspNetCore.Mvc.Infrastructure.ActionSelector.SelectBestCandidate
...
This suggests that you may be still using the legacy routing system backed by IRouter
; otherwise, known as convention-based routing. This method of routing was dropped in 6.0
and is called out in the migration guide. This was not a decision made lightly. I would have liked to keep it for edge cases, but it was fraught with problems and painful to maintain the right behavior. If you had stayed on that path with previous versions, you have probably just been lucky enough to never hit any of the sharp edges. There are many however. Aside from Endpoint Routing being the de facto method going forward, route performance will improve. In the legacy routing system, it was possible to re-enter candidate selection with IActionSelector
. This was very problematic for API Versioning because that meant it had to hook a catch all route and wait to end after all possible paths had been exhausted to make a decision. If it didn't do that, then routing might short-circuit too early with an error response. The most common cause of this behavior is if you had /deliveries/{id}
and /deliveries/{id:int}
across versions. This would lead to a second evaluation of candidates.
Unless I'm otherwise mistaken or missed something, things are not working because you aren't using Endpoint Routing. You must use Endpoint Routing. That is now the only supported routing system.
[ApiVersion(3)]
is defined, but nothing maps to it. You might not have included it, but with an explicit mapping to 1
and 2
, this will be never be matched.accept-language
is far more flexible than a custom headeraccept-language
, if you need it (see strategies for selecting language/culture)Thanks for the suggestion about the languages management, I'll improve it as soon as I can. About the version 3, it is there because I really use it, simply I did not pasted the entire controller since not useful for the purpose. Now the problem is that while I'm trying to enable Endpoint Routing I'm getting this error: and I cannot find what I'm missing. Do you have any idea?
After some more tries I got it run, your help definetly solved the problem. To solve the last error I just needed to refactor also the Program.cs file and avoid using the Startup configuration.
Thank you
Is there an existing issue for this?
Describe the bug
I have just moved from Microsoft.AspNetCore.Mvc.Versioning to Asp.Versioning I have defined two versions for the same route. When I try to perform the request I get this error:
Before the migration everything was working fine, now we would like to move to the Asp.Versioning library since the old one is deprecated.
Expected Behavior
I would expect that the versioning keep working as before.
Steps To Reproduce
The request:
https://localhost/api/deliveries?v=2
This is how I defined the controller and the two routes:
and this is the teh configuration in ConfigureServices in the Startup:
Exceptions (if any)
With *** I'll hide private data
.NET Version
.NET 8
Anything else?
No response