Aspnet-api-versioning: Versioning Gets Ambiguous Routes in Core 2.2

Created on 9 Oct 2018  路  17Comments  路  Source: microsoft/aspnet-api-versioning

When using the Versioning system with a Core 2.2 Preview project, the routing can't differentiate by version #'s if you use the 2.2 Compatibility Flag (it's not required that you leave Core 2.2, just set the compatibility flag to 2.1):

    public void ConfigureServices(IServiceCollection services)
    {
      services.AddApiVersioning(opt =>
      {
        opt.DefaultApiVersion = new ApiVersion(1, 1);
        opt.ReportApiVersions = true;
        opt.AssumeDefaultVersionWhenUnspecified = true;
      });

      services.AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); // <--- Works 
        //.SetCompatibilityVersion(CompatibilityVersion.Version_2_2); // <--- Doesn't Work 
    }

I tried both the 2.1 version of the library and the 3.0-beta-1 and got same result.

My controller looks like this:

  [Route("api/[controller]")]
  [ApiController]
  [ApiVersion("1.0")]
  [ApiVersion("1.1")]
  public class ValuesController : ControllerBase
  {
    // GET api/values
    [HttpGet]
    [MapToApiVersion("1.0")]
    public ActionResult<string> Get()  => "1.0";

    [HttpGet]
    public ActionResult<string> Get11() => "1.1";

  }

Here is a minimal repro case for you to try:

ReproVersioning22.zip

asp.net core

Most helpful comment

3.1 has been published and includes support for _Endpoint Routing_. All of the sample applications have been updated to use _Endpoint Routing_ by default as well. Thanks.

All 17 comments

There is a complete revamp of the routing system coming in 2.2, which API versioning doesn't support - yet. In fact, the IActionSelector doesn't even get used in 2.2 - though it still exists. This is likely why it's not working. It's unfortunate for those on the bleeding edge, but otherwise its actually good news. I've already met with the ASP.NET team and these changes will fix a number of issues and other limitations currently in the routing system. I'm not entirely sure what the means for API versioning with respect to backward compatibility, though it seems weird that someone would take 2.2 and use 2.1 compatibility. What will likely happen is some side-by-side support until 3.0 when the new routing system is the default and the old flavor is completely removed.

Thanks for the repro. This will be useful in evaluating things against 2.2.

Good luck, I'm showing it in a new course for 2.2, so I wondered if any of this will end up working in 2.2 when it ships or are you implying that in 2.2 you'll have to use the compatibility until 3.0?

Good question.

As I understand it, it will work in 2.2 _as is_ with 2.1 compatibility. I'm not sure what feature options there will be for routing, but there may be an option to take all the new features, but use the old routing. In 3.0 the new routing become the norm and, thus, there is no need for compatibility as it will be the only option. I have no insight into when that will actually happen.

I've been buried with issues (mostly OData) trying to get everything out the door for API versioning 3.0. I hadn't anticipated that the routing changes were finally going to happen (I've been in discussions with some of the pain points for more than a year). Now that I know it's coming, I re-evaluating what's necessary in the API versioning release to make that as painless as possible. I'd rather not have to go to 4.0 unless it's absolutely necessary. Keeping the intricacies of routing orthogonal has been a primary design constraint. That said, now that I know there are some folks out there experimenting with latest features, I'll be sure to circle back around when I have something ready.

Most of the routing works, but this particular case doesn't. Maybe I'll do a pull request and see if I can do a work-around since you're slammed.

Looks like it's the IRouteConstraint that needs to re-written. I don't have time to dig in as deeply as I'd like. I'll have to talk with my publisher about whether to leave out versioning or revisit it in 3.0 when this all works.

Just one more question to be clear, do you think you'll have a solution that doesn't require we turn off Endpoint routing by the time that 2.2 is released? Or are you talking about using compat until 3.0?

Good question. My plan is to have support at the time of 2.2 release. This is something that will be prioritized over other new features as it address a number of long-standing issues. Only significant bugs that _happen_ to pop up will be a barrier. I just up against physics in that realm.

I don't understand the code enough to help at this point, but if you'd like to do a quick skype session, I could take a first stab at it.

Hey @shawnwildermuth, I haven't forgotten about this. I've just about got all the other bugs ironed out for the forthcoming beta 2 release. I _should_ be able to put some time into this later this week or next. If you have a repro project you can share ahead of time, I'll use that to dive into. I don't mind getting on the horn, but I want to make sure I've familiarized myself with everything beforehand. Discovery on a call could be quite consuming of your time. Thanks.

I didn't think you did. As long as we're on track for the 2.2 release, i'd be really happy. I dug into the code but I couldn't get deep enough in without some help to try and take a crack at it.

Any status on this?

Now that Beta 2 is out, I should have more capacity to dig into this. _Crossing my fingers_, but it may even be that the refactoring in the action selector may even solve this issue altogether.

Thanks for the help!

Been revisting this. It's been a while since I last sync'd up with the ASP.NET team so I needed to refresh my memory of the changes. Since the routing system is completely changed, there is definitely quite a bit of refactoring to do on my side to match with the intrinsic 2.2 features; in particular, the new _Endpoint Routing_ feature. The biggest challenge for me will be deciding whether to continue supporting the _legacy_ style of routing which will still be available. It seems like leaving the _legacy_ support makes sense until ASP.NET Core 3.0 and perhaps then retire it. I also need to figure how to detect which style of routing is being used and alter the setup accordingly as it's quite different.

I don't believe the coding effort is all that huge, but the addition of new acceptance testing _may_ be signficant. Depending on the effort required to switch between routing styles will drive my decision to release API versioning 3.0 with it's current routing capabilities and add the new capabilities in 3.1 shortly thereafter or try to incorporate the changes prior to the 3.0 release. The other consideration is that taking on the new routing features will also require developers to upgrade to ASP.NET Core 2.2. These decisions are more strategic than technical, but it's a lot to handle as a one-man show.

In the meantime, my understanding is that you can use 2.2 with API versioning, but only using the legacy routing features. This can be achieved with:

c# services.AddMvcCore( options => options.EnableEndpointRouting = false ); // OR services.AddMvc( options => options.EnableEndpointRouting = false );

This option trumps the implicit _Compatibility Version_ setting as long as it's supported (e.g. setting this to true in 2.1 wouldn't do anything)

That's the current state of the union. I'll see if I can't get some time with the ASP.NET team to mull over some decisions. Ideally, my goal is to coincide the official API Versioning 3.0 release with the ASP.NET Core 2.2 release later this month (they have officially said Q4 2018).

Sounds like in either case, this won't make the 2.2 release (since 4th quarter is almost over and with Connect next week I suspect that's in the cards). Just trying to figure out the best way to teach this in my course that is about to come out without having to revisit it later, but I think i'll just show them this option and explain that it may be unnecessary at some point.

services.AddMvc( options => options.EnableEndpointRouting = false );

This fix the issue on .NET Core 2.2 where MapToApiVersion not working and resulting "The request matched multiple endpoints.".
Any timeline on when it will be upgraded/preview on how it will look like?

3.1 has been published and includes support for _Endpoint Routing_. All of the sample applications have been updated to use _Endpoint Routing_ by default as well. Thanks.

Was this page helpful?
0 / 5 - 0 ratings