Repository navigation
Releases
16.4.0
Summary
Refit 16.4.0 adds opt-in HTTP-aware retries, new query naming and relative URL options, and fixes for parameter binding and response handling. Existing clients keep their current behavior unless you enable the new options.
HTTP-aware retries
HttpRetryHandler works with Refit clients and ordinary HttpClient calls. It needs no extra resilience package or changes to your API interface.
- By default, it allows three retries after the first send for GET, HEAD, OPTIONS and TRACE. It retries HTTP 408, 429, 500, 502, 503 and 504, plus
HttpRequestException. A 403 retries only when the configured delay reader finds a valid timing hint. - The default reader respects standard
Retry-Afterheaders.RetryDelayProviders.Azure,.Aws,.GitHuband.Jiraalso read provider-specific timing headers. Custom readers can useReadHeaderwith seconds, milliseconds, Unix timestamps or date formats. - When no valid hint is available, retries use exponential backoff starting at one second and capped at 30 seconds. Full jitter randomly spreads attempts within that interval. You can disable jitter or choose symmetric variation with
RetryJitterMode.Symmetric. - Server hints are never shortened by jitter. A hint above
MaxDelayreturns the response rather than retrying too early.ServerDelayJitterRatiocan add a small positive variation to a server delay. - Each attempt uses a fresh request with copied headers, options and content metadata. Request bodies are buffered once, with a one MiB default limit. Failed responses are disposed; the final response remains caller-owned. Cancellation covers buffering, sends and waits.
Quick start
Put the retry handler in the client's handler chain, then create your Refit client as usual:
using Refit;
var handler = new HttpRetryHandler(new HttpRetryOptions
{
MaxRetries = 3,
DelayProvider = RetryDelayProviders.GitHub,
})
{
InnerHandler = new HttpClientHandler(),
};
using var client = new HttpClient(handler)
{
BaseAddress = new Uri("https://api.github.com"),
};
var api = RestService.ForGenerated<IGitHubApi>(client);IGitHubApi is your existing Refit interface. Omit DelayProvider to use standard Retry-After handling. With Refit.HttpClientFactory, register a fresh handler for the client:
services.AddRefitGeneratedClient<IGitHubApi>()
.ConfigureHttpClient(static client =>
client.BaseAddress = new Uri("https://api.github.com"))
.AddHttpMessageHandler(static () => new HttpRetryHandler(new HttpRetryOptions
{
DelayProvider = RetryDelayProviders.GitHub,
}));Set MaxRetries = 0 to disable retries. Use ShouldRetry to replace the response rules, and BaseDelay / MaxDelay to tune waits. POST, PUT, PATCH and DELETE require RetryUnsafeMethods = true; enable this only when replay is safe for the endpoint, such as when it supports an idempotency key. Avoid unbounded streaming uploads and stacking this handler with another retry strategy.
An authentication handler inside the retry handler runs on every attempt. HttpClient.Timeout bounds the whole call, including retry waits. For deterministic tests, Refit.Testing adds RetryReply.After, RetryReply.Header and StubHttp.CreateRetryHandler, with TimeProvider support.
Other changes
[Query(Name = "client_id")]names a query parameter or form field.[AliasAs]still takes precedence. The positional[Query("...")]argument remains a nesting delimiter, not an alias; the new opt-in diagnostic RF016 helps catch that mistake.[Url(AllowRelative = true)]accepts relative as well as absolute URLs, using normal URI resolution againstHttpClient.BaseAddress. Existing encoded queries are retained when appending query parameters. Plain[Url]still requires an absolute URL.RefitSettingsnow groups options underSerialization,Url,ExceptionsandRequests. Existing top-level properties remain available and refer to the same settings. Retry options similarly exposeBackoff,ReplayandResponsesgroups.- The generator pipeline and model equality handling were reorganized, with added coverage for inherited interfaces, incremental generation and request construction.
- New tested documentation recipes cover resilience and OpenTelemetry. CI now publishes and runs a consumer of the packed Refit packages under Native AOT on Windows, Linux and macOS, as well as the documentation NativeClient.
- Dependency and build updates include ReactiveUI.Primitives 9 and refreshed test packages and GitHub Actions. Local Refit packages are excluded from Renovate updates.
Fixes
- Route and query parameters whose names differ only by case now bind correctly in generated and reflection-based clients. Exact-case route matches take priority, and sibling query parameters no longer overwrite route values. This also covers mixed ordinary and catch-all placeholders. (#2360)
IApiResponse.ContentHeaders.ContentLengthremains readable after response content is buffered or disposed, including when no explicitContent-Lengthheader was sent. (#2360)- If response buffering fails mid-stream and deserialization then fails because the stream was consumed, Refit surfaces the original buffering exception instead of the misleading deserialization error. Content that remains readable can still be deserialized. (#2360)
- Native AOT smoke publishing on .NET 11 RC2 no longer fails while trying to copy a missing XML documentation file. (#2360)
🗞️ What's Changed
✨ Features
- 57ab320 feat: add a Native AOT package consumer and resilience and telemetry recipes (#2342) @glennawatson
- 92ae878 feat(http): add header-aware retries (#2364) @glennawatson
🐛 Fixes
- 8e03c5e fix: disambiguate case-differing parameters, preserve ContentLength header, and surface buffering exceptions (#2360) @glennawatson
🧹 General Changes
- 695344d ci: keep local Refit packages out of Renovate @glennawatson
- 970bf3e build: remove third-party analyzer packages (#2351) @glennawatson
📦 Dependencies
- 7c2efd1 chore(deps): update dependency tunit to 1.69.16 (#2341) renovate[bot]
- db1db92 chore(deps): update dependency reactiveui.primitives to v9 (#2350) renovate[bot]
- fbf8edd chore(deps): update dependency tunit to 1.72.10 (#2346) renovate[bot]
- e692f9b chore(deps): update dependency tunit to 1.69.21 (#2343) renovate[bot]
- 8d2e79b chore(deps): update github actions (#2353) renovate[bot]
🔗 Full Changelog: v16.3.0...v16.4.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
🤖 Automated services that contributed: renovate[bot]
16.3.0
🗞️ What's Changed
✨ Features
- 053873c feat(analyzers): explain why a method cannot generate and flag unbound route placeholders (#2340) @glennawatson
🔗 Full Changelog: v16.2.0...v16.3.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
16.2.0
🗞️ What's Changed
✨ Features
- d864935 feat(testing): add controllable streams, request capture and a test clock to Refit.Testing (#2337) @glennawatson
- 0418743 feat(bodies): typed JSON Lines uploads from IEnumerable and IAsyncEnumerable (#2338) @glennawatson
🧹 General Changes
- 2ecbf2a chore: update packages, credit Refit's origins, remove stale files (#2336) @glennawatson
- 7aa89fa chore: remove the Jekyll site files now that GitHub Pages redirects to reactiveui.net @glennawatson
✅ Tests
- a463e8a test(bodies): cover the remaining typed JSON Lines branches (#2339) @glennawatson
📝 Documentation
- 5d17ac9 docs(readme): name the programme behind each sponsor @glennawatson
- ceb75e8 docs(readme): link to the ReactiveUI sponsors page @glennawatson
- a330a63 docs(readme): keep the README renderable on nuget.org @glennawatson
- 176ebdb docs: new Refit logo and official sponsor logos @glennawatson
- 7333739 docs(readme): credit OpenAI's Codex for Open Source support @glennawatson
📦 Dependencies
🔗 Full Changelog: v16.1.0...v16.2.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
🤖 Automated services that contributed: renovate[bot]
16.1.0
🗞️ What's Changed
✨ Features
- aa139a2 feat: add lazy paging with generated PagedEnumerable methods (#2332) @glennawatson
- bb98726 feat: register JSON contexts and accept JsonTypeInfo parameters (#2333) @glennawatson
📝 Documentation
- 9df0751 docs: point the code of conduct at the website @glennawatson
📌 Other
- 5106e9c Update copyright year in LICENSE file @glennawatson
🔗 Full Changelog: v16.0.0...v16.1.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
16.0.0
Summary
Refit 16.0.0 is a major version because the .NET 11 assemblies are built without runtime-async. The public API does not change.
Why runtime-async is off
- In .NET 10 and older, the C# compiler adds a state machine to each async method. The state machine stores the local variables and tracks where to resume after each
await. - .NET 11 adds a feature called runtime-async. The runtime does this work instead, so async code can run faster.
- Refit 12.0.0 to 15.2.0 built the .NET 11 assemblies with runtime-async on. We did not use it with older .NET 8-10 nor .NET framework assemblies.
- The feature needs a runtime that supports it. CoreCLR does, and Mono does not.
- Blazor WebAssembly runs on Mono unless you opt into CoreCLR. WASI, Android API levels 21 to 23, and apps that set
UseMonoRuntime=truealso run on Mono. - Refit built with runtime-async can fail in every app that runs on Mono.
- Microsoft builds its framework assemblies twice, once for each runtime. ASP.NET Core turns the feature on only for libraries inside the shared framework, and leaves it off for libraries that also ship on NuGet.
- A NuGet package ships one build for every runtime, so Refit leaves the feature off. The feature is opt-in, so doing nothing is the correct setting.
- Apps that target .NET 10 or older are not affected, because only the .NET 11 assemblies used the feature. Apps on .NET 11 that run on CoreCLR do not get the speed gain inside Refit's own async code.
- You can turn on runtime-async in your own app if it runs only on CoreCLR.
Other changes
- Refit has a documentation website at https://reactiveui.net/documentation/refit/. It has guides for requests, results, clients, serialization and testing, and one page that lists the full API.
- The README is a short overview of the packages, the build requirements and the links to the website.
src/examples/Documentationhas a project for every website page, plus larger samples for topics such as multipart uploads, serializers and compression. Each project builds withRefit.slnxand checks its results against local replies, so none needs a live service.- On older target frameworks, Refit checks the cancellation token before it buffers or reads HTTP content. A token that is already cancelled stops the operation before it starts.
- Doc comments were corrected to match how Refit works. They state that
[Options]sendsOPTIONS, that[Url]accepts an empty path or/, and that[PathPrefix]does not add a leading slash. The Refit.Testing docs state thatVerifyAllCalledignores reusable and fallback routes. - The Blazor WebAssembly sample builds for .NET 10 and .NET 11. It uses a generated client and JSON source generation, and builds without trimmer warnings.
- Refit depends on ReactiveUI.Primitives 8.0.0. On .NET 11, Refit.HttpClientFactory depends on Microsoft.Extensions.Http 11.0.0-rc.1, and other targets depend on 10.0.12.
SECURITY.mdlists the supported versions and explains how to report a vulnerability through GitHub private reporting.- CI workflows drop code scanning of fork pull requests and pass
sourceRefto the shared release workflow. Renovate handles package updates per target framework, and the generator snapshot tests use a small in-repo helper instead of the Verify packages.
🗞️ What's Changed
✨ Features
- 6f0507f feat: expand generated request support & docs (#2329) @glennawatson
- 6445e42 feat: update nuget packages, update Renovate configuration, enhance generator tests, remove unused packages (#2330) @glennawatson
- 1459f55 feature: Remove runtime-async feature from Directory.Build.props (#2331) @glennawatson
🧹 General Changes
- ba8f492 ci: let the shared fork SonarCloud workflow resolve the pull request itself @glennawatson
- 1542153 ci: remove SonarCloud scanning of fork pull requests @glennawatson
- 7b1c3be ci(lock): run the lock workflow at its own time of day @glennawatson
- dd2a75f ci: pass sourceRef to the shared release workflow @glennawatson
📝 Documentation
- c2bd862 docs(readme): link combined API reference @glennawatson
- dee79fc docs: add security policy @glennawatson
📦 Dependencies
- 45fcc59 chore(deps): pin mcr.microsoft.com/dotnet/sdk docker tag to e622deb (#2324) renovate[bot]
- 8b71ed0 chore(deps): update dependency minver to v8 (#2320) renovate[bot]
- 2d89767 chore(deps): update dependency sonaranalyzer.csharp to 10.33.0.1635 (#2316) renovate[bot]
- 2f75847 chore(deps): update dependency microsoft.testing.extensions.codecoverage to 18.11.2 (#2322) renovate[bot]
- 9bf02a3 chore(deps): update dependency verify.tunit to v32 (#2318) renovate[bot]
- 96e91c6 chore(deps): update dependency roslynator.analyzers to v5 (#2317) renovate[bot]
- 47698c4 chore(deps): pin github actions digests (#2323) renovate[bot]
- 5d9fe43 chore(deps): update dependency sonaranalyzer.csharp to 10.34.0.3385 (#2321) renovate[bot]
- 38471c8 chore(deps): update dependency publicapisharp.analyzers to v2 (#2328) renovate[bot]
📌 Other
- bb49573 Update sponsors section in README @glennawatson
- 5106e9c Update copyright year in LICENSE file @glennawatson
🔗 Full Changelog: v15.2.0...v16.0.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
🤖 Automated services that contributed: renovate[bot]
15.2.0
🗞️ What's Changed
✨ Features
- 1643323 feat(body): compress request bodies (#2311) @glennawatson
🐛 Fixes
- 96316a6 fix(debugging): stop debugger displays rendering as a bare null (#2315) @glennawatson
- 05c856a fix(generator): keep the analyzers loadable in Visual Studio (#2309) @glennawatson
- 1dc4377 fix(headers): stop rewriting raw header values (#2310) @glennawatson
📦 Dependencies
🔗 Full Changelog: v15.1.0...v15.2.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
🤖 Automated services that contributed: renovate[bot]
15.1.0
🗞️ What's Changed
🐛 Fixes
- 74cbb64 fix(generator): ship a single Roslyn analyzer slot (#2305) @glennawatson
⚡ Performance
- b455f65 perf(generator): return the request task instead of awaiting it (#2302) @glennawatson
🧹 General Changes
- 0065f72 build: raise the analyzer rules to error and fix the reported code (#2299) @glennawatson
📦 Dependencies
- 46071eb chore(deps): update dependency sonaranalyzer.csharp to 10.32.0.713 (#2303) renovate[bot]
- 51368ea chore(deps): update dependency roslynator.analyzers to 4.16.0 (#2298) renovate[bot]
🔗 Full Changelog: v15.0.0...v15.1.0
🙌 Contributions
💖 Thanks to all the contributors: @glennawatson
🤖 Automated services that contributed: renovate[bot]
15.0.0
🗞️ What's Changed
✨ Features
- 6f5aa73 feat: introduce GeneratedSingleTypeParameterAttributeProvider for single attribute type handling @glennawatson
- 873c8bd feat: keyed refit generated client DI registration (#2297) @rmja
- 0ebbaf4 feat: Implement a more legible Source Code (#2282) @glennawatson @JaviergarcíadelaNocedaArgüelles @jgarciadelanoceda
🐛 Fixes
- 285cc67 fix: resolve generated clients when the module initializer runs late (#2289) @glennawatson
- ee87983 fix: differentiate explicitly empty string delimiter from "no delimiter" (#2295) @rmja
- 69ee15f fix: Propagate cancellation exceptions during response buffering (#2284) @lukas @radixy0
🧹 General Changes
- dc278d3 chore(renovate): group related dependency cohorts (#2286) @glennawatson
- 5d4a0b9 build: track public API with PublicApiSharp.Analyzers (#2288) @glennawatson
📦 Dependencies
- 7d6f29d chore(deps): update dependency sonaranalyzer.csharp to 10.31.0.145097 (#2290) @renovate[bot]
- 52345ac chore(deps): update dependency verify.tunit to 31.28.0 (#2291) @renovate[bot]
🔗 Full Changelog: v14.0.1...v15.0.0
🙌 Contributions
🌱 New contributors since the last release: @lukas, @radixy0
💖 Thanks to all the contributors: @glennawatson, @jgarciadelanoceda, @lukas, @radixy0, @rmja
🤖 Automated services that contributed: @renovate[bot]
15.0.0-beta.1
🗞️ What's Changed
✨ Features
- 6f5aa73 feat: introduce GeneratedSingleTypeParameterAttributeProvider for single attribute type handling @glennawatson
- 0ebbaf4 feat: Implement a more legible Source Code (#2282) @glennawatson @JaviergarcíadelaNocedaArgüelles @jgarciadelanoceda
🐛 Fixes
- 285cc67 fix: resolve generated clients when the module initializer runs late (#2289) @glennawatson
- 69ee15f fix: Propagate cancellation exceptions during response buffering (#2284) @lukas @radixy0
🧹 General Changes
- dc278d3 chore(renovate): group related dependency cohorts (#2286) @glennawatson
- 5d4a0b9 build: track public API with PublicApiSharp.Analyzers (#2288) @glennawatson
📦 Dependencies
- 52345ac chore(deps): update dependency verify.tunit to 31.28.0 (#2291) @renovate[bot]
- 7d6f29d chore(deps): update dependency sonaranalyzer.csharp to 10.31.0.145097 (#2290) @renovate[bot]
🔗 Full Changelog: v14.0.1...v15.0.0-beta.1
🙌 Contributions
🌱 New contributors since the last release: @lukas, @radixy0
💖 Thanks to all the contributors: @glennawatson, @JaviergarcíadelaNocedaArgüelles, @jgarciadelanoceda, @lukas, @radixy0
🤖 Automated services that contributed: @renovate[bot]
14.0.1
🗞️ What's Changed
🐛 Fixes
- 132f72d fix(generator): support path and header bindings (#2281) @glennawatson
⚡ Performance
- 2f16caa perf: escape query components in place (#2277) @glennawatson @jgarciadelanoceda
- 6501f88 perf: Use String Interpolation In Code Generation (#2278) @glennawatson @jgarciadelanoceda
🔗 Full Changelog: v14.0.0...v14.0.1
🙌 Contributions
🌱 New contributors since the last release: @JavierGarciadelaNocedaArguelles
💖 Thanks to all the contributors: @glennawatson, @JavierGarciadelaNocedaArguelles, @JaviergarcíadelaNocedaArgüelles, @jgarciadelanoceda