August 12 2025
When Rest API Client is mentioned in .NET, most of us think and most of us use HttpClient which is excellent.
But did you know that there is something better that is also easier to implement?
Have you heard of Refit?
Let's see what it's all about.
Refit is a REST API client library for .NET that allows you to define an API as an interface in your application.
With Refit, you use attributes to define HTTP requests, making it a breeze to call RESTful services.
Built on top of System.Net.Http.HttpClient, Refit takes care of the heavy lifting, including serialization and deserialization of JSON data, allowing you to focus on writing your business logic.
Let's take a look on the example.
In the example, we will use a simple GitHub Public Api.
The GitHub API is a great example for demonstrating how to use Refit due to its rich set of features and documentation.
Let's create a simple client that fetches user information from GitHub. Step 1: Add nuget package Refit.HttpClientFactory:
dotnet add package Refit.HttpClientFactory
Step 2: Define the GitHub API Interface
First, define an interface that represents the GitHub API endpoints you're interested in.
For this example, we'll fetch user details from the GitHub API.
Create a new file IGitHubApi.cs in your project:
using Refit;using System.Threading.Tasks; public interface IGitHubApi{ [Get("/users/{username}")] Task<GitHubUser> GetUserAsync(string username);}
Here, we use the [Get] attribute to specify that GetUserAsync will perform an HTTP GET request to the /users/{username} endpoint.
Step 3: Define the GitHub User Model
Next, create a model that represents the JSON response returned by the GitHub API. Create a new file GitHubUser.cs:
public class GitHubUser{ public string Login { get; set; }; public string Name { get; set; }; public string Company { get; set; }; public int Followers { get; set; }; public int Following { get; set; }; public string AvatarUrl { get; set; };}
This class defines the properties we want to extract from the GitHub API response.
Step 4: Configure Dependency Injection for Refit
Now, let's configure Dependency Injection (DI) for Refit in the Program.cs file:
Open Program.cs and modify it as follows:
builder.Services.AddRefitClient<IGitHubApi>() .ConfigureHttpClient((sp, client) => { var settings = sp.GetRequiredService<IOptions<GitHubSettings>().Value; client.BaseAddress = new Uri(settings.BaseAddress); client.DefaultRequestHeaders.Add("Authorization", settings.AccessToken); client.DefaultRequestHeaders.Add("User-Agent", settings.UserAgent); });
builder.Services.AddRefitClient
This sets up IGitHubApi as a typed client, which Refit will generate for you.
GitHubSettings represents the settings presented via the IOptions pattern, whose values are mostly found in appsettings.json.
And that's it, it is necessary to call the method on the API endpoint where you need it.
var user = await gitHubService.GetUserAsync("StefanTheCode");
If you were to implement this using HttpClient, it would be necessary to create a class that implements IGitHubApi and that somehow uses HttpClient in the GetUserAsync method to call the API and get the data. It would roughly look like this:
public class GitHubApiClient : IGitHubApi{ private readonly HttpClient _httpClient; public GitHubApiClient(HttpClient httpClient) { _httpClient = httpClient; _httpClient.BaseAddress = new Uri("https://api.github.com"); } public async Task<GitHubUser> GetUserAsync(string username) { var response = await _httpClient.GetAsync($"/users/{username}"); response.EnsureSuccessStatusCode(); var user = await response.Content.ReadFromJsonAsync<GitHubUser>(); return user; }}
Here we see the advantages of Refit.
Instead of writing this much code, it is necessary to define only the interface and then Refit will generate everything we need to call the Api endpoint in the background.
Very useful isn't it?
By using Refit, we significantly reduce the amount of boilerplate code required to make HTTP requests and handle responses.
This leads to:
Improved Readability: Your API interfaces are clearly defined and separate from the business logic, making the code easier to read and maintain.
Easier Testing: Since the API interactions are defined as interfaces, they can be easily mocked during testing.
Seamless Integration: Refit integrates smoothly with modern .NET features such as dependency injection, HttpClientFactory, and advanced serialization options, making it a perfect fit for .NET 8 projects.
Refit is a powerful library that, when combined with .NET 8, offers a robust and streamlined approach to consuming REST APIs.
In just a few lines of code, we set up a GitHub API client, fetched user data, and displayed it in the console.
This simplicity, combined with .NET 8’s performance improvements and modern language features, makes Refit an excellent choice for developers looking to build efficient and maintainable applications.
That's all from me for today. Make a coffee and try Refit.
Stop arguing about code style. In this course you get a production-proven setup with analyzers, CI quality gates, and architecture tests — the exact system I use in real projects. Join here.
Not sure yet? Grab the free Starter Kit — a drop-in setup with the essentials from Module 01.
Design Patterns that Deliver — Solve real problems with 5 battle-tested patterns (Builder, Decorator, Strategy, Adapter, Mediator) using practical, real-world examples. Trusted by 650+ developers.
Just getting started? Design Patterns Simplified covers 10 essential patterns in a beginner-friendly, 30-page guide for just $9.95.
Every Monday morning, I share 1 actionable tip on C#, .NET & Architecture that you can use right away. Join here.
Join 20,000+ subscribers who mass-improve their .NET skills with actionable tips on C#, Architecture & Best Practices.
Subscribe to the TheCodeMan.net and be among the 20,000+ subscribers gaining practical tips and resources to enhance your .NET expertise.