I want to continue the conversation from #153
I propose removing version checks from the content-type header altogether, here is why:
content-type has nothing to do with content negotiation which is what this feature is built aroundDiscussions are always welcome.
It's going to take some convincing, especially given that you can easily change the behavior on your end and it breaks the existing, default behavior. It _might_ be changed in the future.
To address your points individually...
_Standardization_ is certainly the most compelling argument and I've been aware of this from the beginning. It's broader than GET and POST. There are 3 categories - that I'm aware of:
GET and would be expected to be negotiated by media type via the Accept headerPOST, PATCH \ MERGE, and PUT.DELETE, which is not meant to accept input or provide output, even I have seen such implementationsIt sounds like we agree on Accept for GET so there's no need to discuss that further (hopefully). Writes are an odd case. I do not think you'll ever be able to uniformly _standardize_ the input for all cases. Your presumption that Accept helps _standardize_ the interaction assumes that there is output, which there may not be. It's completely reasonable for there to be no output. Consider something like POST movie/123/rate that sends a body, but returns nothing (say 204 (No Content)). Requiring or otherwise using Accept in this context is _unnatural_. On the other hand, if a client provides content, it must specify Content-Type, regardless of whether any output is returned. This is the most sensible place to specify the API version. If there is both input and output, hence Content-Type and Accept, Content-Type is _preferrable_ because there is only one thing to negotiate. The server either accepts that media type and version or returns 415 (Unsupported Media Type). A POST _could_ have a scenario where there are neither inputs nor outputs, but that would be rare. DELETE is the real enigma because it's not _supposed_ to have input or output. Requiring Accept or Content-Type in that scenario is odd. I realized that mismatch, but there was no nice solution other than to use either header - typically Accept, even though it was meaningless. This issue has now been addressed by enabling API _version-neutral_ methods down to the action level. There is a high probably that DELETE is _version-neutral_. I can't even think of a scenario where the surface area of an API would change for DELETE, but it could.
content-type has nothing to do with content negotiation which is what this feature is built aroundI would argue that is not accurate statement. There is still negotiation on the server. While it's true that there isn't a list to negotiate from, the server still has to accept it. This is client-driven negotiation. If the server will not accept the media type provided by the client in this scenario, it will return 415 (Unsupported Media Type). This is equivalent to the server saying, _"I do not understand or cannot process this."_ This is the reciprocal of 406 (Not Acceptable), which is the server telling the client, _"I cannot produce the format that you asked for."_
I don't really see what the relevance of this statement is. The ease by which a method is achieved is irrelevant to its _correctness_. I would argue that a defining attribute of an _Application Programming Interface_ (API) is that it is called via code and not directly driven by user interaction. That being said, I do think this point highlights why the query string method has become increasing more popular. While it's not as RESTful as media type negotiation, it's much easier to integrate with all clients and without breaking any REST constraints (as opposed to something like _URL versioning_ - yuck).
There are also difficulties in using and advertising content-type in swagger docs and unexpected behavior with API version discovery.
For example, as it is written today to make swagger advertise correctly I need to decorate my Post or Put with
[Consumes(MediaTypeNames.Application.Json + ";v=1.1")]
or
[Consumes("application/json;v=1.1")]
That is redundant with the ApiVersion attribute. Adding the above fixes swagger docs, but that also prevents the ApiVersion code from finding the action. Receiving a 400 ApiVersionNotSupported.
Thank you for taking the time to consider this. I understand wanting to stick with the semantics of which headers we send naturally by rest verb or expected result code. But I would err on the side of simplicity where there is no strict requirement for complexity.
Github, for example, erred on the side of simplicity by standardizing on Accept, since the majority of endpoints will provide data and a general rule is easier to remember than specifics. https://developer.github.com/v3/#current-version
I'm not sure where you found an example about HTML. Maybe it was related to UIs with MVC? If you can find the link or location, I'm happy to clarify or elaborate.
For the second issue, I presume you are using Swashbuckle for Swagger/OpenAPI integration. I'm aware that adding the API version in the media type is redundant and brittle, but there's a solution to that - use the API Explorer extensions. You might already be doing that, but things aren't working. Why you ask? I don't know all the history in Swashbuckle and I don't keep up with all the changes they are making, but - historically - not all of the information provided by the API Explorer, and hence the API Versioning extensions, are being leveraged by Swashbuckle or the OpenAPI libraries. I don't know why and I've tried to collaborate in the past. I don't get hard resistance, but not much work has been to drive that forward. I can't _make_ those libraries use the standard information provided. I'm already at capacity or I'd probably submit PRs.
As an example, if you have:
c#
[Consumes("application/json")]
[Produces("application/json")]
for API version 3.0, the API Versioning extensions will enhance the API Explorer information like this:

Unfortunately, that's not what Swashbuckle or Open API is doing (I'm not sure who the offender is). They are _assuming_ applicationj/json for some reason.
With a little bit of work on your end, you can _beat_ things into submission:


... and it will all work.
This was achieved by a few small tweaks in SwaggerDefaultValues.cs in the Swagger example project. There are other gaps filled by this class too.
Finally, GitHub has a pretty decent API and I do often cite it as one of the few, big APIs that use media type negotiation. I can understand why they chose to standardize on Accept. I looked a little more at what the MediaTypeApiVersionReader does again. Currently, it short circuits if Content-Type is present, which _could_ lead to a 4xx response if no API version is present. I _think_ it would be acceptable to _consider_ Accept, if and only if, Content-Type does not have an API version parameter. This would have full backward compatibility with the existing implementation and would give you the same GitHub-like API experience using Accept. I need to cogitate on that just a bit before you get too excited, but I think that is _reasonable_.
In case you were wondering, this is what the code looks like:
This was whipped up in minutes. It's not to be taken as battle-tested, production-ready code.
```c#
if ( apiDescription.SupportedRequestFormats.Count > 0 && operation.RequestBody.Content.Values.Count > 0 )
{
var mediaType = operation.RequestBody.Content.Values.First();
operation.RequestBody.Content.Clear();
operation.RequestBody.Content.Add( apiDescription.SupportedRequestFormats[0].MediaType, mediaType );
}
foreach ( var response in operation.Responses.Values )
{
if ( response.Content.Count == 0 )
{
continue;
}
var mediaType = response.Content.Values.First();
response.Content.Clear();
response.Content.Add( apiDescription.SupportedResponseTypes[0].ApiResponseFormats[0].MediaType, mediaType );
}
```
Make adjustments as you need and/or request Swashbuckle/OpenAPI do the _right_ thing. They are able to implement this without any dependency on API Versioning.
It would seem that my response resolved your issue or, at least, unblocked you. If I missed something, we can re-open the issue or create a new one. Thanks.