-
Notifications
You must be signed in to change notification settings - Fork 704
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Single version-neutral controller and DefaultApiVersion set to neutral causes AmbiguousMatchException #1011
Comments
You had me ... for a second. The problem is that The thing that determines if something is API version-neutral is The reason you are seeing this error happen is due to how things are grouped for routing. First and foremost, you will likely encounter problems if the only thing you have are version-neutral APIs; it's as if you didn't version anything. In previous implementations, version-neutral endpoints would respond to any valid API version, which is arguably wrong. Now, a version-neutral endpoint will respond to any defined API version in your application. If you don't have any versioned endpoints, version-neutral can only match the unspecified use case. This can similarly problematic for OpenAPI documentation. This is a rare, nonsensical scenario IMHO. If you have all version-neutral APIs, then you shouldn't need API Versioning. The versioned route tree edges are grouped on an API version. Since a version-neutral API doesn't have any specific API versions, it doesn't have a value to group on. This is a use case for On one hand, you could call this a 🐞. It's certainly not expected and arguably violates POLA. However, It would appear that your goal is to have otherwise unversioned APIs be version-neutral. This is certainly possible, but know that there be 🐉🐉🐉. The most significant concern is that if any version-neutral API ever needs to become versioned, you need to be very careful about changing things. This behavior is all or nothing. To go from version-neutral to versioned, you'd need to split and explicitly support all of the previous versions. If you have a sound versioning policy - say N-2, that might not be too horrible of a thing to fix. The case where a client doesn't specify an API version is the scenario that will haunt you. In that case, the client might break. In order to continue allowing no API version, you'd have to enable There are some alternate solutions. There isn't a built-in convention for version-neutral APIs, but you could easily create one. For example, like the Version-neutral APIs are also a sleazy way of opting out of versioning. If that is your intent and you have many controllers in this scenario, there is a better way to handle that. This type of edge case is advanced, but straight forward. The [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class UnversionedAttribute : Attribute { } [Unversioned]
[ApiController]
[Route("[controller]")]
public sealed class TestController : ControllerBase
{
[HttpGet]
public IActionResult Get() => Ok();
} public sealed class VersionedSpecification : IApiControllerSpecification
{
public bool IsSatisifiedBy(ControllerModel controller) =>
!controller.Attributes.OfType<UnversionedAttribute>().Any();
} builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IApiControllerSpecification, VersionedSpecification>()); Now anything with I need to think a little bit more as to whether there is a way to protect you from yourself if you configure things this way, but ultimately the reported behavior is expected because it's misconfigured. |
Thanks a lot for the thorough explanation. I must admit that our setup is slightly complex as we split three different API types based on area, where one of the APIs are unversioned. The APIs are all hosted within the same application and we’ve split them between a “private” unversioned API, only accessible by the web app in the system, an “internal user”, versioned, API accessible by the front end of other systems and finally an “internal system”, versioned, API accessible by the backend of other systems. |
Is there an existing issue for this?
Describe the bug
To start, this is a bit obscure and likely not something a lot of people will ever encounter.
If I set
DefaultApiVersion
toApiVersion.Neutral
and only have a single controller annotated with[ApiVersionNeutral]
I'm getting an AmbiguousMatchException.I've tracked it down to how the
ApiVersionMatcherPolicy
handles neutral endpoints, and it seems like the endpoint is added twice in this specific case here.The issue might also be in the
ApiVersionCollator
, I'm not sure.Expected Behavior
I would expect the endpoint to be accessible as normal, and did not expect an exception to happen, although I understand the configuration is unusual.
Steps To Reproduce
Exceptions (if any)
By removing or commenting out the region in the repro, you will get the following error:
.NET Version
7.0.306
Anything else?
My team spent quite some time getting to the bottom of this, and in our case, the solution was to simply remove the
[ApiVersionNeutral]
attribute.However, I don't think this is expected behavior and it was very difficult to track down.
The text was updated successfully, but these errors were encountered: