Support multiple version constructor in ApiVersionAttribute
See original GitHub issueSince ApiVersionAttribute
extends ApiVersionsBaseAttribute
witch supports multiple versions in the constructor, would be great to made it visible in the ApiVersionAttribute
.
Issue Analytics
- State:
- Created 5 years ago
- Comments:10
Top Results From Across the Web
Support multiple version constructor in ApiVersionAttribute
Since ApiVersionAttribute extends ApiVersionsBaseAttribute witch supports multiple versions in the constructor, would be great to made it ...
Read more >How to use API versioning in ASP.NET Core
Note how the major version and minor version are passed to the constructor of the ApiVersion class at the time of assigning the...
Read more >APIController checking for all supported versions without ...
1 Answer 1 ... An API version is nothing more than metadata. It is not an IActionConstraint nor a route constraint. The attributes...
Read more >How To Support Multiple Versions of ASP.NET Core Web API
Learn how to implement versioning in ASP.NET Core Web APIs using query strings, request URIs, HTTP request headers, or media types.
Read more >What every ASP.NET Core Web API project needs - Part 2
Open WeatherForecastController file and add the ApiVersion attribute and modify the Route attribute value: [ApiController] [ApiVersion("1.0")] ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
@sdepouw The first issue that you are seeing is that ApiVersionAttribute is not inherited. This is by design. Honestly, I’m of the opinion that inheritance is the wrong approach for HTTP APIs, but the reasoning is more than my dogma. If API versions were inherited, you can easily get into a situation where 2 different super types implement the same versions and routes. While it’s true that it is technically possible to avoid that from happening it is not clear in code. You also cannot uninherit a method or API version if it was allowed. In the spirit of the Principal of Least Astonishment and intention-revealing code, API versions must be explicitly declared on the types that implement them. One of the original core design principles was that API version information should be pure metadata. In alignment to that, you can use whatever you want for inheritance, but then you must explicitly state which implementations have which versions.
I’ve outline some of the original history around the design of one value per attribute. I ultimately settled on a single value because it aligned with the attribute name (singular) and it is very easy to create your own multi-value attribute. The implementation shown above is correct, although you might prefer another name such as ApiVersionsAttribute. The built-in ApiVersionsBaseAttribute is the foundation for several of the built-in attributes, but it intentionally does not implement IApiVersionProvider because the implementation varies on the derived types. Again - the example above does illustrate putting that all together.
API Versioning does not have a concept of no version, unless the controller is completely ignored/filtered out (ex: a UI controller). As you’ve observed, if you do not specify any versions or mappings, there is an assumed default (e.g.
ApiVersioningOptions.DefaultApiVersion
). Once you apply an explicit mapping, any mapping, that convention is negated. This allows existing APIs to be grandfathered in without touching them. Once you touch anything, then all bets are off and you have to explicitly specify everything.Based on your description of the problem, I think you would be better off using conventions as opposed to attributes. These are not mutually exclusive and you can use both, if you want. For example:
Then, you’d just add it in the configuration:
You mentioned something about groups. This approach could be enhanced with your own attribute, metadata, or additional convention so that you apply a set of API versions to specific groups. An attribute would probably be the most appropriate and can be accessed via
controllerModel.Attributes
.You can also map specific versions to methods this way; however, unless all of your controllers use the same names (which I suspect they don’t), it is probably messy. The best option here is probably to continue using
[MapToApiVersion]
. No built-in convention exists actions for that, but you could create one that works similar toVersionByNamespaceConvention. If your actions use suffixes such asGetV1
,GetV2
, and so on, you can figure out which action methods map to which version. If multiple versions map, then you might need something likeGetV1V2
. It’s easy to identify action methods because they must bepublic
, notstatic
, and have not have[NoAction]
applied. You can probably even get the pre-filtered list fromcontrollerModel.Actions
without any additional work.If conventions aren’t workable for you, then I would still recommend taking the attribute approach a step further. Rather than just list all of the versions for each application of the attribute, wrap it up in a single, more meaningful attribute. Something like:
You could then apply this to your controllers, or even your base controller, with
[GroupXApiVersions]
.Regardless of which way you go, there is way that you an centrally manage your defined API versions. Careful consideration has to be made as to what is provided out-of-the-box and what you can customize or extend. There might not be a constructor for ApiVersionAttribute that allows multiple versions, but you can create one in ~10 lines of code. That’s a fairly low bar in my box. 😉
I hope that helps.
cc @eliamartani