Overview
Refit 12.0 is a large release centred on a near-complete rewrite of how requests are built. The source generator now constructs HTTP requests inline at compile time instead of going through the reflection pipeline, making generated clients faster and friendly to trimming and Native AOT. On top of that foundation it adds response streaming, JSON Lines, naming-convention presets, and a batch of long-standing fixes. Two small, well-scoped breaking changes are called out below.
Highlights
- Reflection-free, AOT-ready source generation. Eligible interface methods now have their request (URI, headers, body, request properties) built directly in generated code, with the reflection request-builder kept only as a fallback for shapes that cannot be generated inline. Form bodies flatten through compiled, source-generated field descriptors. The generator itself was modernised and optimised, and ships analyzer diagnostics and code fixes. There is also a generated-only client-creation mode and a build-time switch for generated request building.
IAsyncEnumerable<T>response streaming. Stream large responses, auto-detecting a JSON array vs JSON Lines from the content type, generated inline on the hot path.- JSON Lines request bodies.
[Body(BodySerializationMethod.JsonLines)]plus a streamingJsonLinesContent(application/x-ndjson), wired through both the reflection and source-gen paths. - Naming-convention presets.
RefitSettings.CamelCase()/SnakeCase()/KebabCase()configure query keys, form-url-encoded keys, and JSON body property names consistently, plus snake/kebab URL key formatters. Opt-in, so existing behaviour is unchanged. - Response ergonomics.
EnsureSuccessStatusCodeAsync()/EnsureSuccessfulAsync()are now available directly onIApiResponse<T>; a newIsSuccessfulWithContent(andHasContent) gives a single, mock-safe success-with-content check; nullable annotations onIApiResponse<T>were corrected to be sound. - URL and route control. Opt-in RFC 3986 / HttpClient-style URL resolution via
RefitSettings.UrlResolution, andRefitSettings.AllowUnmatchedRouteParametersto leave an unmatched{token}for aDelegatingHandlerto rewrite. - Faster JSON. A fast-path serialization option (
SystemTextJsonContentSerializer.GetFastPathJsonSerializerOptions()) and buffered/streamed request-body modes that run through it. - Smaller additions.
[Query(SerializeNull = true)]to send a null property askey=instead of omitting it, and a publicUniqueName.ForType<T>()to resolve the generatedIHttpClientFactoryclient name. - Fixes. Multipart
Guid/DateTime/DateTimeOffset/TimeSpan(andDateOnly/TimeOnly) are sent as plain text (#2016); property-level[Query(delimiter, prefix)]is honoured when flattening complex objects (#1334);[Query(Format = "")]serializes a complex value viaToString()(#1281); andIApiResponse<T>no longer shadows base members (#1933).
Breaking changes and migration
IApiResponse<T>no longer shadows base members. Thenew-shadowedError,ContentHeaders,IsSuccessStatusCode, andIsSuccessfulmembers are removed from the generic interface. Source that reads these still compiles (they bind to the inherited base members), but code compiled against v8-v11 that bound to the generic-interface slots needs a recompile. If you relied onIsSuccessfulto narrowContentto non-null on anIApiResponse<T>-typed value, switch toHasContent/IsSuccessfulWithContent.- The default
System.Text.Jsonserializer now reads numbers from JSON strings (NumberHandling = AllowReadingFromString). Opt back out withNumberHandling = JsonNumberHandling.Stricton yourJsonSerializerOptions.
๐๏ธ What's Changed
๐ฅ Breaking Changes
- 8b70ca1 break: request-building fixes, JSON Lines, and response ergonomics (#2155) @glennawatson
- 3881cc6 break: add IAsyncEnumerable streaming and opt-in URL, route and JSON serialization modes (#2157) @glennawatson
โจ Features
- 6f2e43d feat: respect naming conventions across query, form and JSON body (#2154) @glennawatson
- 196cd49 feat: add IsSuccessfulWithContent and correct IApiResponse nullable annotations (#2159) @glennawatson
- e28a384 feat: generate request construction to avoid reflection pipeline (#2150) @glennawatson
- 98982b4 feat: reflection-free generated form serialization, opt-in null values, and public UniqueName (#2164) @glennawatson
- bf488d6 feat: improve generated clients for AOT (#2151) @glennawatson
โป๏ธ Refactoring
- 3fd4ce6 refactor: replace System.Reactive with ReactiveUI.Primitives and integrate observable test helpers (#2152) @glennawatson
- c7c14b4 refactor: align Refit with rxui coding standards and modernize (#2149) @glennawatson
โก Performance
- 3717256 perf: modernize and optimize the Refit source generator (#2148) @glennawatson
๐งน General Changes
- 0aae034 build: update StyleSharp.Analyzers to 3.13.4 and align editorconfig (#2163) @glennawatson
๐ Full Changelog: v11.2.0...v12.0.0
๐ Contributions
๐ Thanks to all the contributors: @glennawatson