Pablo Recalde
Pablo Recalde

Reputation: 3571

Refit: versioned routes

We were using Refit on one of your API's to create and share a Client package for that API.

ICategoryApi.cs

[Post("/category")]
Task CreateCategoryAsync([Body] CategoryCommandDto createCategoryCommandDto);

and everything was working fine with a controller like

CategoryController.cs

[ApiController]
[Route("[controller]")]
public class CategoriesController : ControllerBase
{
    [HttpPost]
    [ProducesResponseType((int)HttpStatusCode.Created)]
    [ProducesResponseType((int)HttpStatusCode.BadRequest)]
    public async Task<IActionResult> CreateCategory([FromBody] CategoryCommandDto createCategoryCommandDto)
    {
          //some code
    }
}

The problem is that now we've added api versioning, and we choosed to version by route.

So now the endpoint /category looks like /v1/category and we will create a /v2/category soon.

Is there a way to configure refit (through attributes or similar) for it to understand my versioned routes?

I want to avoid having to write a new client for every new version of the API and including the version in the endpoint route like

ICategoryApiV1.cs

[Post("/v1/category")]
Task CreateCategoryAsync([Body] CategoryCommandDto createCategoryCommandDto);

Imagine that the client is bigger and has a lot of methods, not just one. Also not all the methods may change between versions.

Upvotes: 1

Views: 1731

Answers (1)

Support Ukraine
Support Ukraine

Reputation: 1026

You can achieve this in a different way: 1) Use like an argument from method;

ICategoryApiV1.cs

[Post("/{v}/category")]
Task CreateCategoryAsync([Body] CategoryCommandDto createCategoryCommandDto, [AliasAs("v")]int version = 1);

2) Define a property inside of CategoryCommandDto;

public class CategoryCommandDto
{
    // Properties can be read-only and [AliasAs] isn't required
    public int v { get { return 1; } }
      .....
}

3) Define a baseUrl for httpClient during ICategoryApi creation

services.AddRefitClient<ICategoryApi>()
    .ConfigureHttpClient(c => c.BaseAddress = new Uri($"https://api.example.com/{version}"));

4) Or if you need some advanced calculation you can add a custom HttpHandler and configure inside yours client.

services.AddRefitClient<ICategoryApi>(settings)
        .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.example.com"));
        .AddHttpMessageHandler<VersionHandler>()

Upvotes: 2

Related Questions