Open
Description
Background and Motivation
Extension method which operate on IServiceCollection
type are usually chainable.
When I saw examples it was not immeidately obvious that AddMvc
is not the same from Asp.Net Core:
public static IApiVersioningBuilder AddMvc(this IApiVersioningBuilder builder)
vs
public static IMvcBuilder AddMvc(this IServiceCollection services)
It took me a while to understand why versioning was not working for controllers.
Proposed API
My proposal is to add alternative method named WithMvcSupport()
which, IMO, will cause less confusion and will be more descriptive. (Also WithApiExplorerSupport
)
Usage Examples
services.AddApiVersioning(cfg => { ...}).WithMvcSupport().WithApiExplorerSupport();
Risks
If this proposal is accepted, the interface will epand, so is the need to support it. Maybe old methods can be deprecated with time.
Metadata
Metadata
Assignees
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
commonsensesoftware commentedon May 1, 2024
This is intentional and by design. The new approach was outlined in the roadmap 2 years ago. The full gambit is:
Existing users have been thrown off a bit because
AddMvc
wasn't necessary in the past, but that's because Minimal APIs didn't exist nor were supported.Only some DI extensions are directly chainable. As you've even shown above,
IServiceCollection.AddMvc
doesn't returnIServiceCollection
, it returnsIMvcBuilder
.AddMvcCore
returnsIMvcCoreBuilder
.IApiVersioningBuilder
works in a similar fashion. All of these builders provideIServiceCollection Services { get; }
.If you wanted to make one big chain, you still can with:
There were several motivations behind this change:
services.AddVersionedApiExplorer()
beforeservices.AddApiVersioning()
services.AddApiVersioning().AddApiExplorer()
vsservices.AddVersionedApiExplorer()
IApiVersioningBuilder
In addition to the roadmap, this information has been conveyed in:
I've gone to great lengths to try and make it concise, but still obvious. There are only two scenarios that seem to consistently hang people up:
IApiVersioningBuilder.AddMvc
with controllers, which I don't have a better solution for.AddMvc
adds the full MVC stack versus MVC Core (which is silly for APIs so I thought it was obvious; in hindsight perhapsAddMvcCore
would have been better)The convention for adding services, even via a builder, is with the
AddXXX
prefix. You can see that even IApiVersioningBuilder.AddApiExplorer has to call through toIServicesCollection.AddMvcCore → IMvcCoreBuilder →
IMvcCoreBuilder.AddApiExplorer.At this point, I'm not really inclined to change things. There hasn't been an outcry from the community. I'm still willing to entertain the idea however. I will leave the issue open and if there is a significant upvote, I'll consider it. Aliases are nice, but they also have the risk of causing confusion and changing them will result in a breaking change - at some point (there's no point in having both - forever).
voroninp commentedon May 2, 2024
Then I'd propose to emphasize in wiki and examples that these methods are not the standard one from the framework.
commonsensesoftware commentedon May 2, 2024
In the wiki, there is already the text:
There's even an entire page dedicated to migration that convers all of the changes that came in
6.0
that should help people moving fromMicrosoft.AspNetCore.Mvc.Versioning
toAsp.Versioning.Mvc
.Perhaps more text in the examples. The examples are setup to boil things down to just the bare minimum API Versioning configuration with comments and options highlighted for the common knobs that someone might want to turn. The example itself is kind of the documentation. IMHO, it should be obvious that everything shown is working and required. Turning a knob is one thing, but removing a knob, such as removing the call to
.AddMvc()
, should be expected to break things.The simplified setup for
WebApplication
removes the necessity forAddMvcCore
andAddMvc
. That should also be a signal that it's different. It would probably be more obvious if they were still side-by-side:This is actually the case with OData, which requires:
voroninp commentedon May 2, 2024
Let me explain how it was for me.
The last time I used your package was before minimal APIs.
For minimal APIs to work you also do not need to call standard
AddMvc()
orAddMvcCore()
. So when I read that comment, my thought was: "Thank you, I know." 😂My code was:
Then I added versioning:
MVC added? Check.
Versioning added? Check.
;-)
commonsensesoftware commentedon May 2, 2024
Yep, I get the surprise and there was no great way to fully advertise that. Behavioral changes always concern me the most because they are the least obvious and hardest to find. Unfortunately, they aren't always fully avoidable.
It's been 2+ years, so I could update the announcement banner to reflect a migration notice and like to the appropriate wiki topic instead of just an announcement. Would that have - perhaps - made things slightly more obvious? That's pretty quick and easy change.
voroninp commentedon May 2, 2024
I guess so.
But you know the curse of knowledge. :-) It's always hard to predict how those who are unaware can be surprised:-)
commonsensesoftware commentedon May 2, 2024
POLA is part of every decision. Unfortunately, it's just not always easy to advertise changes.
GiviKDev commentedon May 17, 2025
Hi all,
I spent about 5-6 hours debugging why versioning was not working and even after reading the docs multiple times I completely missed this line:
I assumed that in an ASP NET Core 9.0 Web API project with controllers I did not need to add MVC support. None of the LLMs I tried could identify this as the root cause, probably because MVC feels more tied to full MVC apps than to Web APIs. 😄
I think this note should be added to the official ASP NET Core docs.
I also have two suggestions:
Rename
AddMvc
toAddControllers
Or better yet, move the versioning extension onto
IMvcBuilder
so you can write:That would make the intent much clearer.