Refit¶
Run the complete page example.
When your app needs data from a web service, you want the call to be easy to read and use. Refit lets you describe that call on a C# interface. You specify the service's route and the values it needs, then call the interface method to make the request.
Refit generates the implementation during the build. It fills in the URL, headers and body,
sends the request through HttpClient, and reads the reply into your C# model.
These examples use .NET 10 and C# 14 as their baseline. All C# 14 features are available. Examples for another target framework say so explicitly.
You keep control of the HTTP client and can share settings for JSON, authorization and error handling. The walkthrough below builds a first call, then the subject pages explain the choices in more detail.
Install the Refit NuGet package in the project that declares your interface.
dotnet add package Refit
Your first request¶
1. Choose a reply type. This service returns a person's ID and name as JSON. JSON is a text format for objects, lists and values.
internal sealed record Person(int Id, string Name);
2. Describe the request. [Get] selects the HTTP GET method. A GET asks a service to read data.
The {id} part is a route placeholder. Refit replaces it with the method's id argument.
An interface like this is the contract between your app and the service.
internal interface IPeopleApi
{
[Get("/people/{id}")]
Task<Person> GetPersonAsync(int id, CancellationToken cancellationToken);
}
3. Register the JSON types. Refit reads and writes JSON with System.Text.Json, and takes advantage of its
source generation.
You declare a JSON context: a partial class that derives from JsonSerializerContext and lists your model types.
The System.Text.Json source generator fills it in when you build, so nothing inspects your models through reflection
at runtime. SampleJsonContext is only the name this example gives its class. Give yours any name.
Use the same context when you publish a Native AOT app.
Add using System.Text.Json; and using System.Text.Json.Serialization; for the JSON types.
Keep the JsonSerializerDefaults.Web line. It makes the context read the camelCase names that most services send.
JSON and generated metadata explains what goes wrong without it.
[JsonSourceGenerationOptions(JsonSerializerDefaults.Web)]
[JsonSerializable(typeof(Person))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(Person[]))]
[JsonSerializable(typeof(List<Person>))]
internal sealed partial class SampleJsonContext : JsonSerializerContext;
4. Reuse one HTTP client. Create the HTTP client when your app starts and reuse it for calls.
Set its BaseAddress to the root of the API. The examples on these pages call this client httpClient.
HttpClient httpClient = new() { BaseAddress = new Uri("https://people.example") };
The runnable samples supply a local client that answers each request, so they run without a web server.
5. Create the implementation and call it. RestService.ForGenerated<T> uses the implementation
that Refit generated during the build. Pass your context's Default instance as the second argument.
This call asks for https://people.example/people/1. Add using Refit; to use Refit's types.
IPeopleApi api = RestService.ForGenerated<IPeopleApi>(httpClient, SampleJsonContext.Default);
Person person = await api.GetPersonAsync(1, cancellationToken);
Console.WriteLine(person.Name); // Ada
Pass the caller's CancellationToken so the request stops when a screen closes or the user cancels.
Pass CancellationToken.None when nothing can cancel the call.
Pass settings instead of a context¶
RefitSettings holds the serializer and the other choices for a client, such as headers and error handling.
You can build your own JsonSerializerOptions, wrap them in a serializer and pass the settings instead of the context.
Pick this form when you have options to share, need full control, or want one options object
elsewhere in your app. The short path above needs no options object. This form makes you assign the
TypeInfoResolver yourself and keep the options unchanged after first use.
private static readonly JsonSerializerOptions JsonOptions = new(SampleJsonContext.Default.Options) { TypeInfoResolver = SampleJsonContext.Default };
RefitSettings settings = new(new SystemTextJsonContentSerializer(JsonOptions));
IPeopleApi withSettings = RestService.ForGenerated<IPeopleApi>(httpClient, settings);
Person fromSettings = await withSettings.GetPersonAsync(1, cancellationToken); // fromSettings == person
Create a client covers the settings form in detail.
Find a topic¶
| Page | What you can do |
|---|---|
| API reference | Find types, overloads, parameters and return values across all topics on one page. |
| Why use Refit? | Compare an interface contract with a raw HTTP implementation. |
| Client creation and settings | Create generated clients, configure settings and register clients with dependency injection. |
| Routes and HTTP methods | Choose a method, fill a route, and inspect a request before sending it. |
| Return types | Choose Task<T>, ValueTask<T>, IObservable<T> or a response wrapper. |
| Streaming replies | Read a JSON array, JSON Lines or server-sent events with IAsyncEnumerable<T>. |
| Pagination | Read every item of a paged list, such as an S3, Azure or GitHub listing, with await foreach. |
| JSON and generated metadata | Register a JSON context, keep your serializer settings, pass metadata to a method and check missing registrations. |
| AOT and generated clients | Generate request and JSON code for apps that compile ahead of time. |
| Testing clients | Supply local replies, inspect requests and check which routes were called. |
Refit uses ReactiveUI.Primitives inside its runtime.
Your API methods expose C# types such as ValueTask<T> and IObservable<T>.
You can await a reply or use LINQ-style operators to shape it.
Run the examples¶
The documentation examples live in folders named for their topic. Each page links to its folder. They reference the Refit source projects, including the generator that creates the client implementation. Website blocks can show a focused subset of the complete example. Setup and runtime checks stay in the source project when the page does not need them.
From the Refit checkout's src folder, run:
dotnet run --project examples/Documentation/Documentation.csproj -c Release
The program supplies local HTTP replies and checks the documented results.
Its Common/SampleHost.cs owns the HTTP client for the whole run.
Its Program.cs calls each topic's example and disposes the host when the run ends.