Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 82 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
![Refit](images/logo.png)

## Refit: The automatic type-safe REST library for .NET Core, Xamarin and .NET
## Refit: The automatic type-safe REST library for modern .NET

[![Build](https://github.com/reactiveui/refit/actions/workflows/ci-build.yml/badge.svg)](https://github.com/reactiveui/refit/actions/workflows/ci-build.yml) [![codecov](https://codecov.io/github/reactiveui/refit/branch/main/graph/badge.svg?token=2guEgHsDU2)](https://codecov.io/github/reactiveui/refit)

Expand Down Expand Up @@ -28,7 +28,7 @@ var gitHubApi = RestService.For<IGitHubApi>("https://api.github.com");
var octocat = await gitHubApi.GetUser("octocat");
```

.NET Core supports registering via HttpClientFactory
.NET supports registering Refit clients via HttpClientFactory:

```csharp
services
Expand All @@ -42,6 +42,8 @@ services
* [Where does this work?](#where-does-this-work)
* [Breaking changes in 6.x](#breaking-changes-in-6x)
* [Breaking changes in 11.x](#breaking-changes-in-11x)
* [Source generation](#source-generation)
* [Generated request building](#generated-request-building)
* [API Attributes](#api-attributes)
* [Querystrings](#querystrings)
* [Dynamic Querystring Parameters](#dynamic-querystring-parameters)
Expand Down Expand Up @@ -86,11 +88,11 @@ Refit is sponsored by the following:

### Where does this work?

Refit currently supports the following platforms and any .NET Standard 2.0 target:
Refit currently supports the following platforms and modern .NET targets:

* WinUI
* Desktop .NET Framework 4.6.2+
* .NET 8 / 9 / 10
* .NET 8 / 9 / 10 / 11
* Blazor
* Uno Platform

Expand Down Expand Up @@ -159,6 +161,81 @@ mark those properties as non-null.
The original `IApiResponse.IsSuccessful` and `IApiResponse.IsSuccessStatusCode` properties can still be used to check if
the response was received and is successful.

### Source generation

Refit ships Roslyn source generators with the main `Refit` package. Projects that reference Refit through
`PackageReference` get generated client implementations at build time without adding another package.

The generated clients are still created with the normal APIs:

```csharp
var api = RestService.For<IGitHubApi>("https://api.github.com");
```

or through `Refit.HttpClientFactory`:

```csharp
services
.AddRefitClient<IGitHubApi>()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("https://api.github.com"));
```

The generator uses the same `RefitSettings` you pass to `RestService.For<T>` or `AddRefitClient<T>`. That means generated
clients continue to honor settings such as:

* `ContentSerializer`
* `UrlParameterFormatter`
* `UrlParameterKeyFormatter`
* `CollectionFormat`
* `AuthorizationHeaderValueGetter`
* `ExceptionFactory`
* `DeserializationExceptionFactory`
* `HttpRequestMessageOptions`
* `Version` and `VersionPolicy`

#### Generated request building

Refit's source generator now emits request construction directly for supported methods by default. Instead of generating
a method body that calls the reflective runtime request-building pipeline through `BuildRestResultFuncForMethod`, the
generated client can create the `HttpRequestMessage`, apply headers/properties/body content, and dispatch it through
Refit's generated-request runtime helpers.

This default path reduces runtime reflection, method metadata lookup, object-array argument packing, and delegate
construction for request shapes the generator can safely model. It currently covers common request features including:

* static `[Headers]`
* dynamic `[Header]` parameters
* `[HeaderCollection]` dictionaries
* `[Body]` content
* `[Property]` parameters
* `[Property]` interface properties
* cancellation tokens
* `Task`, `Task<T>`, `Task<ApiResponse<T>>`, and related response wrappers

If a method uses a shape the generator cannot safely emit yet, Refit falls back to the existing runtime request-builder
path for that method.

You can explicitly turn generated request building off in a project file:

```xml
<PropertyGroup>
<RefitGeneratedRequestBuilding>false</RefitGeneratedRequestBuilding>
</PropertyGroup>
```

That keeps the source-generated interface implementation but uses the legacy reflective request-building call path
inside generated methods.

If you need to disable Refit source generation entirely, set:

```xml
<PropertyGroup>
<DisableRefitSourceGenerator>true</DisableRefitSourceGenerator>
</PropertyGroup>
```

Most applications should leave both settings unset.

### API Attributes

Every method must have an HTTP attribute that provides the request method and
Expand Down Expand Up @@ -1425,7 +1502,7 @@ internal class ApiClient : IApiClient

### Using HttpClientFactory

Refit has first class support for the ASP.Net Core 2.1 HttpClientFactory. Add a reference to `Refit.HttpClientFactory`
Refit has first class support for `IHttpClientFactory`. Add a reference to `Refit.HttpClientFactory`
and call
the provided extension method in your `ConfigureServices` method to configure your Refit interface:

Expand Down
2 changes: 0 additions & 2 deletions config/filelist.txt

This file was deleted.

13 changes: 0 additions & 13 deletions config/signclient.json

This file was deleted.

57 changes: 48 additions & 9 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,61 @@
<IsTestProject>$(MSBuildProjectName.EndsWith('Tests'))</IsTestProject>
<DebugType>embedded</DebugType>
<Authors>ReactiveUI and Contributors</Authors>
<Company>ReactiveUI and Contributors</Company>
<Copyright>Copyright (c) ReactiveUI and Contributors</Copyright>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/reactiveui/refit</PackageProjectUrl>
<PackageIcon>logo.png</PackageIcon>
<PackageReadmeFile>README.md</PackageReadmeFile>
<RepositoryUrl>https://github.com/reactiveui/refit</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
<DefaultLanguage>en-US</DefaultLanguage>
<Description>The automatic type-safe REST library for Xamarin and .NET</Description>
<PackageDescription>Type-safe REST API clients for .NET, generated from annotated interfaces and optimized for modern HttpClient, System.Text.Json, source generation, trimming, and AOT scenarios.</PackageDescription>
<PackageTags>refit;rest;http;httpclient;api-client;typed-client;source-generator;roslyn;system-text-json;json;aot;trimming</PackageTags>
<PackageReleaseNotes>https://github.com/reactiveui/refit/releases</PackageReleaseNotes>
<NoPackageAnalysis>true</NoPackageAnalysis>
<LangVersion>preview</LangVersion>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<LangVersion>latest</LangVersion>
<Platform>AnyCPU</Platform>

<EnableNETAnalyzers>true</EnableNETAnalyzers>
<AnalysisLevel>latest</AnalysisLevel>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<RunAnalyzers>true</RunAnalyzers>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<ReportAnalyzer>true</ReportAnalyzer>
<Nullable>enable</Nullable>

<WarningsAsErrors>nullable;CS4014</WarningsAsErrors>

<ImplicitUsings>true</ImplicitUsings>
<ImplicitUsings>enable</ImplicitUsings>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

<!-- Emit source-generator output to obj/Generated so generated code is inspectable/diffable. -->
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(MSBuildProjectDirectory)/obj/Generated</CompilerGeneratedFilesOutputPath>

<!-- Enable building Windows-specific targets on non-Windows platforms. -->
<EnableWindowsTargeting>true</EnableWindowsTargeting>
</PropertyGroup>

<!-- Target Framework Monikers. EnableWindowsTargeting lets the netfx/Windows legs build anywhere. -->
<PropertyGroup>
<RefitGeneratorTargets>netstandard2.0</RefitGeneratorTargets>
<RefitFrameworkTargets>net462;net470;net471;net472;net48;net481</RefitFrameworkTargets>
<RefitModernTargets>net8.0;net9.0;net10.0;net11.0</RefitModernTargets>
<RefitShippingTargets>$(RefitFrameworkTargets);$(RefitModernTargets)</RefitShippingTargets>
<RefitTestTargets>$(RefitModernTargets)</RefitTestTargets>
<RefitBenchmarkTargets>$(RefitModernTargets)</RefitBenchmarkTargets>
<RefitTargets>$(RefitShippingTargets)</RefitTargets>

<!-- Enable building Windows-specific targets on non-Windows platforms -->
<EnableWindowsTargeting>true</EnableWindowsTargeting>
</PropertyGroup>

<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<PropertyGroup Condition="'$(IsTestProject)' == 'true'">
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
<TUnitImplicitUsings>true</TUnitImplicitUsings>
<TUnitAssertionsImplicitUsings>true</TUnitAssertionsImplicitUsings>
</PropertyGroup>

<!-- AOT/trim analyzers on net8.0+ (netfx doesn't support them). -->
Expand All @@ -56,6 +70,10 @@
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
</PropertyGroup>

<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net11.0'))">
<Features>$(Features);runtime-async=on</Features>
</PropertyGroup>

<ItemGroup>
<None Include="$(RepositoryRoot)images\logo.png" Pack="true" PackagePath="\" Visible="false"/>
<None Include="$(RepositoryRoot)LICENSE" Pack="true" PackagePath="LICENSE"/>
Expand All @@ -70,6 +88,7 @@
</ItemGroup>

<ItemGroup Condition="'$(IsTestProject)' != 'true'">
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All"/>
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" PrivateAssets="All"/>
</ItemGroup>

Expand All @@ -81,6 +100,23 @@
<Compile Include="$(MSBuildThisFileDirectory)Polyfills\*.cs" Link="Polyfills\%(Filename)%(Extension)"/>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="$(MSBuildThisFileDirectory)Polyfills\ArgumentExceptionHelper.cs" Link="Polyfills\ArgumentExceptionHelper.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)Polyfills\ArgumentOutOfRangeExceptionHelper.cs" Link="Polyfills\ArgumentOutOfRangeExceptionHelper.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)Polyfills\CallerArgumentExpressionAttribute.cs" Link="Polyfills\CallerArgumentExpressionAttribute.cs"/>
<Compile Include="$(MSBuildThisFileDirectory)Polyfills\NotNullAttribute.cs" Link="Polyfills\NotNullAttribute.cs"/>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net4')) or '$(TargetFramework)' == 'netstandard2.0'">
<Using Include="Refit.Internal.ArgumentExceptionHelper" Alias="ArgumentExceptionHelper"/>
<Using Include="Refit.Internal.ArgumentOutOfRangeExceptionHelper" Alias="ArgumentOutOfRangeExceptionHelper"/>
</ItemGroup>

<ItemGroup Condition="!$(TargetFramework.StartsWith('net4')) and '$(TargetFramework)' != 'netstandard2.0'">
<Using Include="System.ArgumentNullException" Alias="ArgumentExceptionHelper"/>
<Using Include="System.ArgumentOutOfRangeException" Alias="ArgumentOutOfRangeExceptionHelper"/>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.StartsWith('net4'))">
<PackageReference Include="System.Net.Http"/>
<Reference Include="System.Net.Http"/>
Expand All @@ -103,6 +139,10 @@
<!-- MinVer (versioning) — replaces Nerdbank.GitVersioning. Floor at 10.2
so untagged builds produce 10.2.x-alpha.0.<height> until a v10.2.x
(or later) tag is reachable. -->
<PropertyGroup>
<SolutionDir Condition="'$(SolutionDir)' == ''">$(MSBuildThisFileDirectory)</SolutionDir>
</PropertyGroup>

<PropertyGroup>
<MinVerAutoIncrement>minor</MinVerAutoIncrement>
<MinVerDefaultPreReleaseIdentifiers>alpha.0</MinVerDefaultPreReleaseIdentifiers>
Expand All @@ -111,7 +151,6 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All"/>
<PackageReference Include="MinVer" PrivateAssets="all"/>
<PackageReference Include="StyleSharp.Analyzers" PrivateAssets="all"/>
<PackageReference Include="Roslynator.Analyzers" PrivateAssets="All"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
<Nullable>enable</Nullable>
<DefineConstants>$(DefineConstants);ROSLYN_4</DefineConstants>
<MsCACSharpVersion>4.8.0</MsCACSharpVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

Expand All @@ -20,6 +19,11 @@

<ItemGroup>
<InternalsVisibleTo Include="Refit.Tests"/>
<InternalsVisibleTo Include="Refit.GeneratorTests"/>
</ItemGroup>

<ItemGroup>
<Compile Include="..\InterfaceStubGenerator.Shared\**\*.cs" LinkBase="InterfaceStubGenerator.Shared"/>
</ItemGroup>

<Target Name="SetBuildVer" AfterTargets="GetBuildVersion" BeforeTargets="SetCloudBuildVersionVars;SetCloudBuildNumberWithVersion">
Expand All @@ -29,6 +33,4 @@
</PropertyGroup>
</Target>

<Import Project="..\InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.projitems" Label="Shared"/>

</Project>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
Expand All @@ -9,7 +9,6 @@
<Nullable>enable</Nullable>
<DefineConstants>$(DefineConstants);ROSLYN_4;ROSLYN_5</DefineConstants>
<MsCACSharpVersion>5.0.0</MsCACSharpVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>

Expand All @@ -18,13 +17,19 @@
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" PrivateAssets="all"/>
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="Refit.GeneratorTests"/>
</ItemGroup>

<ItemGroup>
<Compile Include="..\InterfaceStubGenerator.Shared\**\*.cs" LinkBase="InterfaceStubGenerator.Shared"/>
</ItemGroup>

<Target Name="SetBuildVer" AfterTargets="GetBuildVersion" BeforeTargets="SetCloudBuildVersionVars;SetCloudBuildNumberWithVersion">
<PropertyGroup>
<Version>$(BuildVersion)</Version>
<AssemblyVersion>$(BuildVersionSimple)</AssemblyVersion>
</PropertyGroup>
</Target>

<Import Project="..\InterfaceStubGenerator.Shared\InterfaceStubGenerator.Shared.projitems" Label="Shared"/>

</Project>
Loading
Loading