Releases: reactiveui/refit
Release list
13.1.0
🗞️ What's Changed
- Fixed the
CS0436build error fromPrimitivesR3BridgeGeneratedAttribute(#2176, #2194). BumpsReactiveUI.Primitivesto 6.0.0, which moves the R3 bridge generator out of the runtime package. Projects usingInternalsVisibleTo(e.g. test projects) build again, and the<Analyzer Remove=... />workaround is no longer needed. - Path parameters now use generated request building instead of reflection (#2174), so they work with
AddRefitGeneratedClientand NativeAOT. Now coversenum,Guid,DateTime/DateTimeOffset/DateOnly/TimeOnly/TimeSpan, all integer widths (incl.Int128/UInt128/Half), and anyIFormattable(#2193).
✨ Features
- b592413 feat: add generated request building support for path parameters in the URL. (#2174) @calebkiage @glennawatson
- 9bc6754 feat: support more path parameter types in generated request building (#2193) @glennawatson
🧹 General Changes
- ac79c76 build: update NuGet dependencies (#2198) @glennawatson
🔗 Full Changelog: v13.0.0...13.1.0
🙌 Contributions
🌱 New contributors since the last release: @calebkiage
💖 Thanks to all the contributors: @calebkiage, @glennawatson
13.0.0
🗞️ What's Changed
Refit 13 is a major release focused on security hardening and a brand-new testing package.
- Security hardening (#2181) — closes issues found in a security audit. XML deserialization is now protected against XXE (external entity) attacks, the Newtonsoft.Json integration no longer honours unsafe
TypeNameHandlingby default (blocking type-confusion/deserialization attacks), and sensitive values (auth headers, tokens) are now redacted from exception and log output. This is the main reason for the major version bump: if you relied on permissive Newtonsoft type handling you may need to opt back in explicitly. - New
Refit.Testingpackage (#2184) — a first-party way to stub and verify Refit clients in tests without spinning up a realHttpClient. Supply canned responses for interface calls and assert which requests your code made, instead of hand-rollingHttpMessageHandlerfakes. - R3 bridge analyzer fix (#2186) — corrects the removal target for the R3 bridge analyzer.
- CI and documentation tidy-ups for SonarCloud on fork pull requests.
✨ Features
- cc24382 feat: security hardening from audit (XXE, Newtonsoft type handling, redaction) (#2181) @glennawatson
- 339cb8d feat: add Refit.Testing package for stubbing and verifying clients (#2184) @glennawatson
🧹 General Changes
- 5d272c8 ci: run SonarCloud on fork pull requests @glennawatson
📝 Documentation
- 533bbbe docs: slim fork-PR SonarCloud wrapper comments @glennawatson
📌 Other
- c0bbb5a [codex] Fix R3 bridge analyzer removal target (#2186) @ChrisPulman
🔗 Full Changelog: v12.1.0...v13.0.0
🙌 Contributions
💖 Thanks to all the contributors: @ChrisPulman, @glennawatson
12.1.0
🗞️ What's Changed
✨ Features
- 89f17ae feat: AOT-safe generated-only client DI registration and case-insensitive problem+json detection (#2172) @glennawatson
- b31e9fe feat: read sent request body and synchronously inspect the error body on ApiException (#2175) @glennawatson
🐛 Fixes
- e3ec13f fix: correctly annotate error out parameters for nullable flow (#2177) @HulinCedric
📝 Documentation
- db33053 docs: document v12 breaking changes and update package versions (#2180) @ChrisPulman
📦 Dependencies
🔗 Full Changelog: v12.0.0...12.1.0
🙌 Contributions
💖 Thanks to all the contributors: @ChrisPulman, @glennawatson, @HulinCedric
🤖 Automated services that contributed: @renovate[bot]
12.0.0
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.
This release also removed netstandard2.0 and netstandard2.1 support. You should to use net462/net8 as your base lines, and use multiple targets if you need to target both.
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
11.2.0
🗞️ What's Changed
🐛 Fixes
- 13882da fix: honor parameter-level CollectionFormat for inner collections (#2144) @glennawatson
- 54a8e62 fix: ValidationApiException propagates ContentHeaders and uses configured serializer (#2146) @glennawatson
- d694baf fix: populate ApiException.Content when deserialization fails (#2145) @glennawatson
🔗 Full Changelog: v11.1.0...v11.2.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
11.1.0
🗞️ What's Changed
🐛 Fixes
- be08706 Fix: serialize body by runtime type for interface/abstract parameters (#2118) (#2119) @HulinCedric
- d58ce5a fix: keep only baseline analyzer on legacy toolchains (#2136) @glennawatson
- 10ab2ce fix: handle empty responses and edge cases in JSON serialization (#2138) @ChrisPulman @glennawatson
- f9a24ab fix: clearer error when a response has no request message (#2141) @glennawatson
- 98868fa fix: detect nullable CancellationToken parameters (#2139) @glennawatson
- 7a3489e fix: correct URL and query string building edge cases (#2137) @glennawatson
- 8f9b460 fix: request building edge cases for headers, query and enum params (#2140) @glennawatson
🧹 General Changes
- 988d17a build: adopt central package management and modernize MSBuild (#2142) @glennawatson
📝 Documentation
- 2989a5e docs: Fix Refit 10 typo that should be Refit 11 (#2143) @PressXtoChris
📦 Dependencies
- b71c90c Update dotnet monorepo (#2123) @renovate[bot]
- b2e3c17 Update ASP.NET Core (#2122) @renovate[bot]
- 5f67752 chore(deps): update dotnet monorepo to v8 (#2130) @renovate[bot]
- 780979c Update Microsoft.Testing to 18.8.0 (#2126) @renovate[bot]
🔗 Full Changelog: v11.0.1...v11.1.0
🙌 Contributions
🌱 New contributors since the last release: @HulinCedric
💖 Thanks to all the contributors: @ChrisPulman, @glennawatson, @HulinCedric, @PressXtoChris
🤖 Automated services that contributed: @renovate[bot]
11.0.1
🗞️ What's Changed
🧹 General Changes
- 484edf6 build: default examples to IsPackable=false @glennawatson
📌 Other
🔗 Full Changelog: v11.0.0...11.0.1
🙌 Contributions
🌱 New contributors since the last release: @xIceFox
💖 Thanks to all the contributors: @glennawatson, @xIceFox
11.0.0
⚠️ This is a breaking release (major: 10.x → 11.0.0)
11.0.0 reworks Refit's error/exception model and tightens interface validation. Most apps will compile, but code that inspects ApiResponse.Error, reads StatusCode, or catches transport exceptions around Refit calls will need changes. These are the same breaking changes that briefly shipped in the now‑delisted 10.1.7 and were reported by the community in #2114.
💡 Need a drop‑in, non‑breaking replacement for
10.1.6? Use10.2.0— it is10.1.6re‑signed with a valid certificate (the10.1.6cert was revoked, see #2114). Move to11.0.0when you're ready to adopt the changes below.
💥 What changed & how to migrate
1. ApiResponse<T>.Error is now ApiExceptionBase? (was ApiException?) (#2052)
A new abstract base ApiExceptionBase now sits under both ApiException and the new ApiRequestException. ApiExceptionBase does not expose Content / HasContent — those still live on ApiException.
// before
string? body = response.Error?.Content;
// after — narrow to ApiException first
if (response.Error is ApiException apiEx)
{
string? body = apiEx.Content; // Content/HasContent are on ApiException
}2. New ApiRequestException wraps transport/connection failures (#2052)
Exceptions thrown by HttpClient.SendAsync before a response arrives — HttpRequestException (DNS/host unreachable), TaskCanceledException (timeouts), etc. — are now wrapped in ApiRequestException : ApiExceptionBase, carrying the full request context. For ApiResponse<T> return types these are now surfaced via .Error instead of only being thrown, so you no longer need a separate try/catch and IsSuccessful check.
// catching transport errors: catch the base (or ApiRequestException) now
catch (ApiExceptionBase ex) { /* covers ApiException + ApiRequestException */ }3. ApiResponse<T>.StatusCode is now nullable (HttpStatusCode?) (#2052)
When the request never reached the server there is no status code. Code that assumed a non‑null value must handle null:
int code = (int)response.StatusCode; // ❌ won't compile / may throw
int? code = (int?)response.StatusCode; // ✅ handle the no-response case4. Stricter interface validation + enum name handling (#2068)
Synchronous return types are now only permitted for generated/non‑public interface members (RestMethodInfo enforces the rule), and the System.Text.Json enum converter now maps serialized names both ways (including JsonStringEnumMemberName on .NET 9+). Interfaces that previously relied on unsupported sync members may now fail generation.
🗞️ What's Changed
✨ Features & Enhancements
- Create
ApiRequestExceptionfor wrappingSendAsyncexceptions (new error model) by @PressXtoChris in #2052 - Support sync interface members & enum names by @ChrisPulman in #2068
- Add
AddRefitClientoverloads and tests by @ChrisPulman in #2084
⚡ Performance
- Replace
Activator.CreateInstancewith direct constructor inApiResponse.Createby @james-s-tayler in #2071 - Avoid extra allocations when deserializing with Newtonsoft.Json by @yzhoholiev in #2085
🐛 Fixes
- Fix for #1959 by @ChrisPulman in #2064
- Fix freezing when reading a string response by @dyatlov-a in #2096
🧹 General & Housekeeping
- Modernize the Refit solution for TUnit, source‑gen AOT, and theme support by @ChrisPulman in #2092
- Add sponsors section and update platforms by @ChrisPulman in #2073, #2074
- Simplify sponsor logos layout in README by @ChrisPulman in #2075
📦 Dependencies
- Update .NET test stack to v10 (TUnit → 1.47.0, Verify.TUnit, Microsoft.Testing CodeCoverage, Test.Sdk) by @renovate[bot] in #2080, #2078, #2097, #2102, #2104, #2106, #2107, #2113, #2086, #2108, #2105, #2112
- Update dotnet monorepo to 10.0.8 by @renovate[bot] in #2076, #2103
- Update Microsoft.Extensions.Http, AspNetCore.WebUtilities, System.Formats.Asn1 to v10 by @renovate[bot] in #2088, #2087, #2090, #2091, #2077
- Update Microsoft.SourceLink.GitHub to 10.0.300 by @renovate[bot] in #2093, #2101
🙌 New Contributors
- @PressXtoChris made their first contribution in #2052
- @yzhoholiev made their first contribution in #2085
- @dyatlov-a made their first contribution in #2096
💖 Contributions
Thanks to everyone who contributed: @ChrisPulman, @PressXtoChris, @james-s-tayler, @yzhoholiev, @dyatlov-a
🤖 Automated services that contributed: @renovate[bot]
🔗 Full Changelog: v10.2.0...v11.0.0
10.2.0
NOTE
This is a re-release of v10.1.6 which had a certificate revoked.
🗞️ What's Changed
🐛 Fixes
- cfe6862 Fixes examples, issues 2058, 1761, 1889, and 2056 (#2061) @ChrisPulman
- 71e7a32 Fix is packable (#2063) @ChrisPulman
🧹 General Changes
- c945712 Update AoT, Add Roslyn 5.0, Update serialisation (#2062) @ChrisPulman
📦 Dependencies
- d3b9f6e chore(deps): update .net test stack (#2054) @ChrisPulman @renovate[bot]
- 804eb41 chore(deps): update .net test stack to v8 (#2057) @renovate[bot]
📌 Other
- 14811e0 Enhance release workflow with new jobs and permissions @ChrisPulman
- 49858e3 Bump version from 10.0 to 10.1 @ChrisPulman
- 2f43b67 Remove productNamespacePrefix from release workflow @ChrisPulman
🔗 Full Changelog: 10.0.1...10.1.6
🙌 Contributions
💖 Thanks to all the contributors: @ChrisPulman
🤖 Automated services that contributed: @renovate[bot]
10.0.1
🗞️ What's Changed
♻️ Refactoring
- af972dd Refactor HttpClientFactoryExtensions to simplify code structure (#2042) @ChrisPulman @zms9110750
🐛 Fixes
- f1af4a5 fix: stop removing trailing single chars from query string (#2045) @baynezy @ChrisPulman
🧹 General Changes
- 0155eeb chore: Bump version from 9.0 to 10.0.x @glennawatson
📦 Dependencies
- dd90c34 chore(deps): update dependency microsoft.codeanalysis.csharp.sourcegenerators.testing to 1.1.3 (#2047) @renovate[bot]
- 6cd4eab chore(deps): update dependency publicapigenerator to 11.5.4 (#2031) @renovate[bot]
- 52d9504 chore(deps): update dependency verify.xunit to 31.8.0 (#2028) @renovate[bot]
- 1b67a8c chore(deps): update dependency verify.xunit to 31.10.0 (#2048) @renovate[bot]
- 49a6731 chore(deps): update dependency verify.xunit to 31.9.3 (#2039) @renovate[bot]
- bce9ae0 chore(deps): update dependency verify.xunit to 31.9.2 (#2038) @renovate[bot]
- ea1ff78 chore(deps): update dependency verify.xunit to 31.9.0 (#2037) @renovate[bot]
- 7f9c7a6 chore(deps): update dessant/lock-threads action to v6 (#2035) @renovate[bot]
- 55783dd chore(deps): update dependency serilog.sinks.console to 6.1.1 (#2023) @renovate[bot]
- e50bf61 chore(deps): update dependency publicapigenerator to 11.5.3 (#2027) @renovate[bot]
🔗 Full Changelog: 9.0.2...10.0.1
🙌 Contributions
🌱 New contributors since the last release: @baynezy, @zms9110750
💖 Thanks to all the contributors: @baynezy, @ChrisPulman, @glennawatson, @zms9110750
🤖 Automated services that contributed: @renovate[bot]