My Notebook: Refit - A type-safe REST library
As the official documentation states,
Refit is a library heavily inspired by Square’s Retrofit library, and it turns your REST API into a live interface
Suppose, you have a REST API hosted somewhere else. The only way you can consume it from any other .NET-based application is to use the built-in HttpClient
or HttpClientFactory
. In a typical scenario that would look something like this,
class Program
{
static async Task Main(string[] args)
{
using var client = new HttpClient();
var content = await client.GetStringAsync("https://jsonplaceholder.typicode.com/posts");
Console.WriteLine(content);
}
}
Working with HttpClient
is a kind of low-level stuff. Refit eases that problem for us. It creates an abstraction over HttpClient
and allows us to work with an interface representing REST endpoints,
A RESTful API for weather forecast service might look like,
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
}
The GET
endpoint can be represented in Refit
by the means of the following interface,
public interface IWeatherAPI
{
[Get("/weatherforcast")]
Task<IEnumerable<WeatherForecast>> Get();
}
Console
Basic usage of Refit
to make API calls is shown below in a .NET console app,
using Refit;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RefitConsole.cs
{
class Program
{
static async Task Main(string[] args)
{
var weatherAPI = RestService.For<IWeatherAPI>("http://localhost:5001");
var forecasts = await weatherAPI.Get();
forecasts.ToList().ForEach(f => Console.WriteLine($"Date: {f.Date}, Celsius: {f.TemperatureC}, Fahrenheit: {f.TemperatureF}, Summary: {f.Summary} \n"));
}
}
public interface IWeatherAPI
{
[Get("/weatherforecast")]
Task<IEnumerable<WeatherForecast>> Get();
}
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public string Summary { get; set; }
public int TemperatureF { get; set; }
}
}
Behind the abstraction, the RestService
class generates an implementation of IWeatherAPI
that uses HttpClient
to make its calls.
Blazor
We can inject the interface and use it to consume the API as well. For a Blazor
client application, it might look like the following,
Additional
Extend six built-in annotations: Get
, Post
, Put
, Delete
, Patch
, and Head
request and add additional options through different attributes. For example, if a POST
request requires multipart data,
public interface IUploadAPI
{
[Multipart]
[Post("/upload")]
Task UploadPhoto([AliasAs("avatar")] StreamPart stream);
}
If a request requires headers to be set,
public interface IUserAPI
{
[Get("/users/{user}")]
Task<User> GetUser(string user, [Header("Authorization")] string authorization);
}
Replace the default JSON content serializer using RefitSettings
,
var weatherAPI = RestService.For<IWeatherAPI>("http://localhost:5001", new RefitSettings
{
ContentSerializer = new XmlContentSerializer()
});
Use Alias
if the name of your parameter doesn't match the name in the URL segment
[Get("/group/{id}/users")]
Task<List<User>> GroupList([AliasAs("id")] int groupId);
Refit
has first-class support forHttpClientFactory
In my honest opinion, it is best suited for Microservices communication over the HTTP channel.
Refit
currently supports the following platforms and any .NET Standard 2.0 target:
- UWP
- Xamarin.Android
- Xamarin.Mac
- Xamarin.iOS
- Desktop .NET 4.6.1
- .NET Core
- Uno Platform