Multiple routes with and without version for the same controller in .NET Core is not working

1.1k views Asked by At

I want to create two routes, one with version and another without, to point to the same controller without decorating the controller methods.

I have defined two routes at the top of the controller, but sending requests using both routes results in 500 Internal server error.

I have the following code snippets:

[ApiController]
[Route("api/docs")]
[Route("api/v1.0/docs")]
public class DocsController : ControllerBase
{
    // . . . .

    [HttpGet]
    public  async Task<IActionResult> GetAsync( . . .)
    { . . }
}

I am looking a way to make the controller to respond the same for both routes. What are some ways to achieve this?

1

There are 1 answers

1
Chris Martinez On

Some specific error details would be useful. The information very well may not be transmitted over the wire for security reasons - and you should never enable that. Your logging infrastructure, be it to some external source or just the console while debugging, should have very detailed information explaining the cause of the problem. A 500 is generally the result of an unhandled exception, which would definitely be logged by the platform.

Without any other information, my first and best guess is that the problem is related to your action name: GetAsync. You should drop the Async suffix unless you really, really want it and understand the ramifications of that. The support for that suffix was dropped in ASP.NET Core 3.0 and is a breaking change. If you happened to just now be upgrading or didn't know about this change, it's really easy to get bitten by:

Breaking Change: Async suffix trimmed from controller action names

Double-Route Registration is definitely possible and supported. It's the only way I know of have an implicit and explicit route template when you version by URL segment. Versioning by URL segment is not something I recommend. It's littered with issues as your service matures and it's not RESTful; it violates the Uniform Interface constraint. It's a popular approach, but know that there be dragons. That choice is in your hands.

If you're looking to add versioning to your ASP.NET Core APIs, might I suggest that you consider ASP.NET Core API Versioning. The package you are looking for is Asp.Versioning.Mvc (note: that it has changed from the older Microsoft.AspNetCore.Mvc.Versioning). There are also several example projects that illustrate various configurations end-to-end.

There are multiple ways that you can configure your application, but based on what you have provided thus far, this is what I would suggest:

[ApiVersion(1.0)]
[ApiController]
[Route("api/[controller]")]
[Route("api/v{version:apiVersion}/[controller]")]
public class DocsController : ControllerBase
{
    [HttpGet]
    public async Task<IActionResult> Get(CancellationToken cancellationToken)
    {
        await Task.Yield();
        return Ok();
    }
}

In your application setup, you would add the following configuration:

services.AddApiVersioning(
          options =>
          {
              // allows requests without an api version;
              // for example, ~/api/docs
              //
              // note: use with caution. this is ONLY meant to be used
              // to support backward compatibility
              options.AssumeDefaultVersionWhenUnspecified = true;
          })        // ← adds minimal api versioning support
         .AddMvc(); // ← add mvc core with controllers versioning support

I'm happy to elaborate further if this does not fully answer your question or you have additional questions. Any other context or details you can provide would be useful.

Disclaimer: I am the owner of the ASP.NET API Versioning project