Description
Hello,
ApiVersionCollator groups actions by controller name and adds versioning metadata, however it fails to filter the actions list to those that are actually defined as having ApiBehavior
(as defined by having IApiBehaviorMetadata
which is added by [ApiController]
attribute on such controllers or base classes thereof).
This leads to the side effect that if a user had 2 controllers with the same name, but different area and different namespace and different everything, one of them is an API and the other is not, accessing the non-API controller will lead to thrown errors from Endpoint routing about unsupported or unspecified API version (depending on whether ApiVersioningOptions.AssumeDefaultVersionWhenUnspecified
is true or false respectively).
This behavior is very confusing and unreasonable for users with no clear way to debug or disambiguate, and there is no logging in the API collation process to troubleshoot this issue.
This kind of scenario is very common in applications such as ecommerce where there will be an API for retrieving products while at the same time an administration controller with the same name to manage such products on the store.
Note: It appears there's some filtering in another area of the library to check for this case, but this filtering is not done on the routing side which I guess is a simple oversight. Anyway, thanks for a very useful library regardless.
Here is a workaround to save others time:
class ApiBehaviorVersionCollator : ApiVersionCollator
{
public ApiBehaviorVersionCollator(IControllerNameConvention namingConvention) : base(namingConvention)
{
}
public override void OnProvidersExecuted(ActionDescriptorProviderContext context)
{
var newContext = new ActionDescriptorProviderContext();
foreach (var action in context.Results)
{
if (!action.EndpointMetadata.OfType<IApiBehaviorMetadata>().Any())
{
continue;
}
newContext.Results.Add(action);
}
base.OnProvidersExecuted(newContext);
}
}
then in the Startup sequence after calling AddApiVersioning().AddMvc()
, search in the service collection for the descriptor having implementation type ApiVersionCollator
and replace it with the one above.
Hope this helps someone.