.NET HTTP Communication with Refit & Resilience
Standardized approach for consuming external APIs using Refit and Microsoft.Extensions.Http.Resilience.
Detail Files
File Content
interfaces.md How to define API contracts, attributes, and return types (ApiResponse<T> ).
usage.md Best practices for consuming ApiResponse<T> , handling errors, and reading headers.
resilience.md Configuring AddStandardResilienceHandler and custom Polly policies.
dtos.md Creating immutable record DTOs with proper JSON mapping.
configuration.md DI registration, Auth handlers, and RefitSettings.
testing.md Patterns for Unit Testing (Moq) and Integration Testing (MockHttp).
Core Principles
-
Refit Interfaces: Define API contracts as interfaces.
-
Immutable DTOs: Use record for all request/response models.
-
Resilience: Apply standard resilience handlers (Polly) via DI.
-
Typed Clients: Always register clients with AddRefitClient<T>() .
-
No Exceptions: Prefer ApiResponse<T> over catching exceptions for flow control.
Quick Start
- Add Packages
dotnet add package Refit.HttpClientFactory dotnet add package Microsoft.Extensions.Http.Resilience
- Define the Interface
using Refit;
public interface IExternalUserApi { [Get("/users/{id}")] Task<ApiResponse<UserResponse>> GetUserAsync(string id, CancellationToken ct); }
- Register in Program.cs
builder.Services .AddRefitClient<IExternalUserApi>() .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.example.com")) .AddStandardResilienceHandler();
MANDATORY Checklist
Component ✅ DO THIS ❌ AVOID THIS
Client AddRefitClient<T>()
new HttpClient()
Models public record Name(string Val);
public class Name { get; set; }
Resilience .AddStandardResilienceHandler()
Manual Policy.Handle<T>()...
Async Pass CancellationToken
.Result or .Wait()
Config BaseAddress in DI Hardcoded URLs in Client