4

I have a problem with middleware hierarchy. I created very simple web api with one controller/action

[Route("api/v1/values")]
  public class ValuesController : Controller
  {
    // GET api/v1/values/5
    [HttpGet("{id}")]
    public async Task<IActionResult> Get(string id)
    {
      return await Task.Run<IActionResult>(() =>
      {
        if (id == "nf")
        {
          return NotFound();
        }

        return Ok($"value: {id}");
      });
    }
  }

I configured routing to use Mvc if match or write Default to response if not.

app.UseMvc();

app.Use(async (context, next) =>
{
  await context.Response.WriteAsync("Default");
});

And this works great, below you can see sample requests/responses:

/api/v1/values/1 -> 200, Body: "value: 1"
/api/v1/values/nf -> 404
/api/v1/values -> "Default"

Great, but then I added ApiVersioning, so controller looks like this:

[ApiVersion("1")]
[Route("api/v{version:apiVersion}/values")]
public class ValuesController : Controller

and I added to Startup : services.AddApiVersioning();. It break routing completely, now for each request i get response "Default", when i remove last app.Use, routing works fine for values controller, but i don't have default middleware. Do you know how i can get responses the same as prevously, but with ApiVersioning?

emilpytka
  • 763
  • 7
  • 19
  • Does it hit your default middleware if you remove `v1` from the request? e.g. `/api/values` – Brad Sep 11 '17 at 09:28
  • Without api versioning yes it hit default middleware; with api versioning it always hit default routing no matter what request i send. – emilpytka Sep 11 '17 at 09:32
  • Based on your setup, this is the expected behavior. API Versioning has it's own _catch-all_ router that is always inserted at the end of the MVC pipeline. If a route _could_ match, but didn't, 400 is returned. In this case, `api/v1/values` is a defined API, but there is no match without an identifier. This will return 400. This behavior has to do with limitations in ASP.NET Core routing. It should be improving in 2.2+. It is definitely possible to combine or use middleware with API versioning. You'll need to describe what you're trying to achieve for better guidance. – Chris Martinez Nov 22 '18 at 00:27

1 Answers1

0

Try this.

[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/foo")]
public class FooController {}

and in Startup class

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

I have tried and it worked for me.

Antoshjke
  • 462
  • 4
  • 22
  • It doesn't work. Every request returns "Default". Could you please also show how loooks your Starutp.Configure method? – emilpytka Sep 14 '17 at 14:02