Simplifying REST Clients with Refit in ASP.NET Core

Learn how to use Refit to reduce boilerplate code when calling REST services and improve application development productivity.

In today’s modern application development, making HTTP calls to external APIs is a common yet sometimes tedious requirement. Often, developers face repeated, boilerplate code when setting up HTTP clients, parsing responses, and handling errors. Refit, a REST library for .NET, addresses these challenges head-on by abstracting the complexities of REST calls into a simple, declarative interface. Today, I’ll dive into how Refit simplifies REST clients in ASP.NET Core, explore its benefits, and provide real-world examples and code snippets to illustrate its usage.

What is Refit?

Refit is a lightweight REST library that turns your REST API into a live interface. With a simple declarative syntax, you only need to define an interface describing your endpoints. Refit then generates the underlying implementation at runtime, allowing you to focus on the business logic rather than the HTTP plumbing.

Setting Up Refit in a Project

Installing packages

In your ASP.NET Core project, use the Package Manager Console or the .NET CLI:

dotnet add package Refit

Define Your API Interface

Create an interface that describes the endpoints of the external service. For demonstration, let’s assume we want to interact with a hypothetical weather API that provides current weather details.

using Refit;
using System.Threading.Tasks;

public interface IWeatherApi
{
    [Get("/weather/current")]
    public Task<WeatherResponse> GetCurrentWeatherAsync([Query] string city);
}

public class WeatherResponse
{
    public string City { get; set; }
    public float Temperature { get; set; }
    public string Description { get; set; }
}

In the above code, we have some important elements:

  • The [Get("/weather/current")] attribute specifies the HTTP GET method and the endpoint path.
  • The [Query] attribute maps the city parameter as a query string parameter.
  • The WeatherResponse class models the expected JSON response.

Configure Refit DI

In your Startup.cs or Program.cs (for .NET 6 and above), register the Refit client with your DI container:

using Refit;

var builder = WebApplication.CreateBuilder(args);

// Register the Refit client
builder.Services.AddRefitClient<IWeatherApi>()
                .ConfigureHttpClient(c =>
                {
                    c.BaseAddress = new Uri("https://api.example.com");
                });

var app = builder.Build();

// Minimal API example to consume the Refit client
app.MapGet("/api/weather", async (IWeatherApi weatherApi, string city) =>
{
    var weather = await weatherApi.GetCurrentWeatherAsync(city);
    return weather;
});

app.Run();

Of course, this is a messy code you should organize into separate classes, but pay special attention to the IWeatherApi registration. Note that as soon as you register the Refit client, you can call the API method GetCurrentWeatherAsync, as simple as that!

Reducing Boilerplate Code

Traditional REST client code often involves manually creating HTTP requests, parsing responses, and handling error scenarios. Want to know more about reducing boilerplate? Read Reducing Boilerplate on .NET IHost Applications

Here’s a brief comparison:

Without Refit

using System.Net.Http;
using System.Text.Json;
using System.Threading.Tasks;

public async Task<WeatherResponse> GetCurrentWeatherAsync(string city)
{
    using var client = new HttpClient { BaseAddress = new Uri("https://api.example.com") };
    var response = await client.GetAsync($"/weather/current?city={city}");
    response.EnsureSuccessStatusCode();
    var content = await response.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<WeatherResponse>(content);
}

With Refit

public interface IWeatherApi
{
    [Get("/weather/current")]
    Task<WeatherResponse> GetCurrentWeatherAsync([Query] string city);
}

With Refit, not only is the code more concise, but it also benefits from automatic serialization/deserialization and better error handling. Such reduction in boilerplate code leads to enhanced readability and maintainability across your application.

Conclusion

Refit offers a modern, efficient, and maintainable approach to consuming REST APIs in ASP.NET Core. By reducing boilerplate code through its declarative syntax and strongly-typed interfaces, Refit improves developer productivity and minimizes the potential for errors. Whether you’re integrating third-party services or handling inter-service communication in a microservices architecture, Refit is a valuable tool that can streamline your HTTP client implementations.

See ya!