Refitter 0.2.2-alpha

This is a prerelease version of Refitter.
There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global Refitter --version 0.2.2-alpha
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Refitter --version 0.2.2-alpha
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Refitter&version=0.2.2-alpha&prerelease
                    
nuke :add-package Refitter --version 0.2.2-alpha
                    

Build Smoke Tests NuGet

Refitter

Refitter is a CLI tool for generating a C# REST API Client using the Refit library.

Installation:

The tool is packaged as a .NET Tool and is published to nuget.org. You can install the latest version of this tool like this:

dotnet tool install --global Refitter --prerelease

Usage:

To generate code from an OpenAPI specifications file, run the following:

$ refitter [path to OpenAPI spec file] --namespace "[Your.Namespace.Of.Choice.GeneratedCode]"

This will generate a file called Output.cs which contains the Refit interface and contract classes generated using NSwag

Here's an example generated output from the Swagger Petstore example

using Refit;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace GeneratedCode
{
    public interface ISwaggerPetstore
    {
        /// <summary>
        /// Update an existing pet by Id
        /// </summary>
        [Put("/pet")]
        Task<Pet> UpdatePet([Body]Pet body);

        /// <summary>
        /// Add a new pet to the store
        /// </summary>
        [Post("/pet")]
        Task<Pet> AddPet([Body]Pet body);

        /// <summary>
        /// Multiple status values can be provided with comma separated strings
        /// </summary>
        [Get("/pet/findByStatus")]
        Task<ICollection<Pet>> FindPetsByStatus();

        /// <summary>
        /// Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
        /// </summary>
        [Get("/pet/findByTags")]
        Task<ICollection<Pet>> FindPetsByTags();

        /// <summary>
        /// Returns a single pet
        /// </summary>
        [Get("/pet/{petId}")]
        Task<Pet> GetPetById(long? petId);

        [Post("/pet/{petId}")]
        Task UpdatePetWithForm(long? petId);

        [Delete("/pet/{petId}")]
        Task DeletePet(long? petId);

        [Post("/pet/{petId}/uploadImage")]
        Task<ApiResponse> UploadFile(long? petId, [Body]StreamPart body);

        /// <summary>
        /// Returns a map of status codes to quantities
        /// </summary>
        [Get("/store/inventory")]
        Task<IDictionary<string, int>> GetInventory();

        /// <summary>
        /// Place a new order in the store
        /// </summary>
        [Post("/store/order")]
        Task<Order> PlaceOrder([Body]Order body);

        /// <summary>
        /// For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
        /// </summary>
        [Get("/store/order/{orderId}")]
        Task<Order> GetOrderById(long? orderId);

        /// <summary>
        /// For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
        /// </summary>
        [Delete("/store/order/{orderId}")]
        Task DeleteOrder(long? orderId);

        /// <summary>
        /// This can only be done by the logged in user.
        /// </summary>
        [Post("/user")]
        Task CreateUser([Body]User body);

        /// <summary>
        /// Creates list of users with given input array
        /// </summary>
        [Post("/user/createWithList")]
        Task<User> CreateUsersWithListInput([Body]ICollection<User> body);

        [Get("/user/login")]
        Task<string> LoginUser();

        [Get("/user/logout")]
        Task LogoutUser();

        [Get("/user/{username}")]
        Task<User> GetUserByName(string username);

        /// <summary>
        /// This can only be done by the logged in user.
        /// </summary>
        [Put("/user/{username}")]
        Task UpdateUser(string username, [Body]User body);

        /// <summary>
        /// This can only be done by the logged in user.
        /// </summary>
        [Delete("/user/{username}")]
        Task DeleteUser(string username);
    }
}

Using the generated code

RestService

Here's an example usage of the generated code above

using Refit;
using System;
using System.Threading.Tasks;

namespace GeneratedCode;

internal class Program
{
    private static async Task Main(string[] args)
    {
        var client = RestService.For<ISwaggerPetstore>("https://petstore3.swagger.io/api/v3");
        var pet = await client.GetPetById(2);

        Console.WriteLine($"Name: {pet.Name}");
        Console.WriteLine($"Category: {pet.Category.Name}");
        Console.WriteLine($"Status: {pet.Status}");
    }
}

The RestService class generates an implementation of ISwaggerPetstore that uses HttpClient to make its calls.

The code above when run will output something like this:

Name: Gatitotototo
Category: Chaucito
Status: Sold

ASP.NET Core and HttpClientFactory

Here's an example Minimal API with the Refit.HttpClientFactory library:

using Refit;
using GeneratedCode;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services
    .AddRefitClient<ISwaggerPetstore>()
    .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://petstore3.swagger.io/api/v3"));

var app = builder.Build();
app.MapGet(
        "/pet/{id:long}",
        async (ISwaggerPetstore petstore, long id) =>
        {
            try
            {
                return Results.Ok(await petstore.GetPetById(id));
            }
            catch (Refit.ApiException e)
            {
                return Results.StatusCode((int)e.StatusCode);
            }
        })
    .WithName("GetPetById")
    .WithOpenApi();

app.UseHttpsRedirection();
app.UseSwaggerUI();
app.UseSwagger();
app.Run();

.NET Core supports registering the generated ISwaggerPetstore interface via HttpClientFactory

The following request to the API above

$ curl -X 'GET' 'https://localhost:5001/pet/1' -H 'accept: application/json'

Returns a response that looks something like this:

{
  "id": 1,
  "name": "Special_char_owner_!@#$^&()`.testing",
  "photoUrls": [
    "https://petstore3.swagger.io/resources/photos/623389095.jpg"
  ],
  "tags": [],
  "status": "Sold"
}

System requirements

.NET 7.0

For tips and tricks on software development, check out my blog

If you find this useful and feel a bit generous then feel free to buy me a coffee ☕

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.7.1 233,711 12/16/2025
1.7.1-preview.87 220 12/16/2025
1.7.0 27,396 11/6/2025
1.7.0-preview.86 155 11/6/2025
1.6.5 268,515 10/6/2025
1.6.5-preview.85 145 10/6/2025
1.6.5-preview.84 135 10/6/2025
1.6.5-preview.83 133 10/6/2025
1.6.5-preview.81 138 10/6/2025
1.6.4 161,912 9/23/2025
1.6.4-preview.80 169 9/20/2025
1.6.3 92,060 9/18/2025
1.6.3-preview.79 269 9/17/2025
1.6.3-preview.78 148 9/13/2025
1.6.3-preview.77 155 9/11/2025
1.6.2 361,328 8/18/2025
1.6.2-preview.76 185 8/13/2025
1.6.1 324,171 7/8/2025
1.6.1-preview.75 159 7/8/2025
1.6.0 129,957 6/17/2025
1.6.0-preview.74 393 6/10/2025
1.5.6 118,352 6/7/2025
1.5.6-preview.73 177 5/31/2025
1.5.5 368,805 5/4/2025
1.5.5-preview.70 93 5/30/2025
1.5.5-preview.69 185 4/30/2025
1.5.4 114,477 4/26/2025
1.5.3 368,983 3/30/2025
1.5.3-preview.68 344 3/23/2025
1.5.3-preview.67 633 1/30/2025
1.5.2 959,959 1/29/2025
1.5.1 85,886 1/25/2025
1.5.1-preview.66 118 1/25/2025
1.5.0 111,582 1/19/2025
1.5.0-preview.65 459 12/8/2024
1.5.0-preview.64 119 12/7/2024
1.5.0-preview.63 134 12/7/2024
1.4.1 956,068 11/20/2024
1.4.1-preview.62 224 11/4/2024
1.4.0 382,421 10/14/2024
1.4.0-preview.61 150 10/7/2024
1.3.2 352,244 9/23/2024
1.3.2-preview.60 127 9/23/2024
1.3.1 72,658 9/20/2024
1.3.0 120,491 9/14/2024
1.2.1-preview.59 112 9/13/2024
1.2.1-preview.58 137 9/11/2024
1.2.1-preview.57 124 9/11/2024
1.2.1-preview.56 138 9/9/2024
1.2.1-preview.55 3,297 9/2/2024
1.2.1-preview.54 4,778 8/29/2024
1.2.0 585,513 8/12/2024
1.2.0-preview.53 5,223 8/4/2024
1.2.0-preview.52 1,905 7/29/2024
1.1.3 383,528 7/19/2024
1.1.3-preview.51 116 7/19/2024
1.1.2 49,147 7/17/2024
1.1.2-preview.50 104 7/16/2024
1.1.2-preview.49 129 7/11/2024
1.1.1 212,438 7/6/2024
1.1.1-preview.48 135 7/4/2024
1.1.1-preview.47 127 7/1/2024
1.1.1-preview.46 138 6/28/2024
1.1.0.45-preview 184 6/25/2024
1.0.2 262,236 6/13/2024
1.0.1 72,010 6/7/2024
1.0.0 270,182 5/3/2024
0.9.9.44-preview 147 4/29/2024
0.9.9 31,771 3/7/2024
0.9.8 27,361 2/27/2024
0.9.7 95,667 2/7/2024
0.9.6 23,888 1/29/2024
0.9.5 65,423 1/15/2024
0.9.4.43-preview 173 1/15/2024
0.9.4 55,746 1/12/2024
0.9.3.42-preview 226 1/10/2024
0.9.2 43,766 1/10/2024
0.9.1 27,569 1/9/2024
0.9.0 26,753 1/9/2024
0.8.7.41-preview 218 1/3/2024
0.8.7.40-preview 219 12/20/2023
0.8.7 78,687 12/18/2023
0.8.6.39-preview 223 12/14/2023
0.8.6.38-preview 263 12/14/2023
0.8.6 27,200 12/11/2023
0.8.5 80,647 11/23/2023
0.8.4 24,028 11/7/2023
0.8.3 23,911 10/31/2023
0.8.2 24,069 10/9/2023
0.8.1 24,542 10/4/2023
0.8.0 25,415 9/23/2023
0.7.5 26,381 9/7/2023
0.7.4 24,015 9/6/2023
0.7.3.37-preview 315 8/25/2023
0.7.3.36-preview 360 8/25/2023
0.7.3.35-preview 353 8/21/2023
0.7.3.34-preview 346 8/15/2023
0.7.3.33-preview 317 8/12/2023
0.7.3 25,687 8/26/2023
0.7.2.32-preview 339 8/7/2023
0.7.2 27,534 8/7/2023
0.7.1.31-preview 348 8/2/2023
0.7.1.30-preview 305 8/2/2023
0.7.1.29-preview 349 8/1/2023
0.7.1 24,369 8/3/2023
0.7.0.28-preview 286 7/28/2023
0.7.0.27-preview 380 7/28/2023
0.7.0.26-preview 378 7/27/2023
0.7.0.23-preview 367 7/27/2023
0.7.0.22-preview 396 7/27/2023
0.7.0.21-preview 344 7/27/2023
0.7.0.20-preview 384 7/27/2023
0.7.0 24,109 7/31/2023
0.6.3 24,866 7/22/2023
0.6.2 39,373 6/22/2023
0.6.1 23,990 6/20/2023
0.6.0 24,401 6/15/2023
0.5.30 24,199 6/12/2023
0.5.29 23,837 6/12/2023
0.5.28 23,851 6/10/2023
0.5.27 23,918 5/24/2023
0.5.26 23,978 5/11/2023
0.5.25 23,898 5/10/2023
0.5.3 23,885 5/5/2023
0.5.2 23,842 5/2/2023
0.5.1 23,848 5/2/2023
0.5.0 23,909 4/28/2023
0.4.2 23,932 4/24/2023
0.4.1 24,124 4/3/2023
0.4.0 24,011 3/24/2023
0.3.17 38,113 3/24/2023
0.3.16 23,923 3/22/2023
0.3.4 23,910 3/22/2023
0.3.3 24,004 3/17/2023
0.3.2 23,989 3/16/2023
0.3.1 23,946 3/14/2023
0.3.0 23,944 3/14/2023
0.2.4-alpha 392 3/1/2023
0.2.3-alpha 311 2/27/2023
0.2.2-alpha 355 2/25/2023
0.2.1-alpha 383 2/25/2023
0.2.0-alpha 335 2/24/2023
0.1.5-alpha 385 2/18/2023
0.1.4-alpha 400 2/17/2023
0.1.3-alpha 417 2/17/2023
0.1.2-alpha 381 2/17/2023