HttpClientGeneratorCode 8.0.0

dotnet add package HttpClientGeneratorCode --version 8.0.0
                    
NuGet\Install-Package HttpClientGeneratorCode -Version 8.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HttpClientGeneratorCode" Version="8.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HttpClientGeneratorCode" Version="8.0.0" />
                    
Directory.Packages.props
<PackageReference Include="HttpClientGeneratorCode" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add HttpClientGeneratorCode --version 8.0.0
                    
#r "nuget: HttpClientGeneratorCode, 8.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package HttpClientGeneratorCode@8.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=HttpClientGeneratorCode&version=8.0.0
                    
Install as a Cake Addin
#tool nuget:?package=HttpClientGeneratorCode&version=8.0.0
                    
Install as a Cake Tool

HttpClient Generator Package

This package generates C# HttpClient code from OpenAPI/Swagger specifications.

📋 Requirements

  • .NET 8.0 or higher
  • ASP.NET Core (for web applications)
  • NSwag.CodeGeneration.CSharp (automatically included)

🚀 Quick Start

Step 1: Generate Client Code

ICodeGeneratorAsync generator = CSharpClientFactory.Create();
await generator.GenerateCSharpClientAsync("https://your-api-url/swagger/v1/swagger.json");

Step 2: Configure in Program.cs

builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<AuthorizationHandler>();
builder.Services.AddHttpClient<GeneratedClient>()
    .AddHttpMessageHandler<AuthorizationHandler>();

Step 3: Add Authorization Handler if needed

public class AuthorizationHandler : DelegatingHandler
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public AuthorizationHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // Get token from user claims (set during login)
        var token = _httpContextAccessor.HttpContext?.User?.FindFirst("access_token")?.Value;

        if (!string.IsNullOrEmpty(token))
        {
            request.Headers.Authorization =
                new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
        }

        return base.SendAsync(request, cancellationToken);
    }
}

📋 Usage Scenarios

Scenario A: Public APIs (No Authorization)

Program.cs:

builder.Services.AddHttpClient<GeneratedClient>();

Controller:

public class ApiController : Controller
{
    private readonly GeneratedClient _client;

    public ApiController(GeneratedClient client)
    {
        _client = client;
    }

    public async Task<IActionResult> GetPublicData()
    {
        var data = await _client.GetPublicDataAsync();
        return View(data);
    }
}

Scenario B: APIs with Login + Bearer Token

This is the most common scenario where you call a login API first, then use the token for other API calls.

Program.cs:

builder.Services.AddHttpContextAccessor();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie();

// For login calls (no auth needed)
builder.Services.AddHttpClient<AuthClient>();

// For protected API calls (with auth)
builder.Services.AddScoped<AuthorizationHandler>();
builder.Services.AddHttpClient<GeneratedClient>()
    .AddHttpMessageHandler<AuthorizationHandler>();

Login Controller:

public class AuthController : Controller
{
    private readonly AuthClient _authClient;

    public AuthController(AuthClient authClient)
    {
        _authClient = authClient;
    }

    [HttpPost]
    public async Task<IActionResult> Login(LoginModel model)
    {
        try
        {
            // Call login API (no token needed)
            var loginResponse = await _authClient.LoginAsync(new LoginRequest
            {
                Username = model.Username,
                Password = model.Password
            });

            if (loginResponse.IsSuccess)
            {
                // Store token in claims for future API calls
                var claims = new List<Claim>
                {
                    new Claim("access_token", loginResponse.Token),
                    new Claim(ClaimTypes.Name, model.Username)
                };

                var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                await HttpContext.SignInAsync(new ClaimsPrincipal(identity));

                return RedirectToAction("Dashboard", "Home");
            }

            ModelState.AddModelError("", "Invalid credentials");
            return View(model);
        }
        catch (Exception ex)
        {
            ModelState.AddModelError("", "Login failed: " + ex.Message);
            return View(model);
        }
    }

    public async Task<IActionResult> Logout()
    {
        await HttpContext.SignOutAsync();
        return RedirectToAction("Login");
    }
}

Protected API Controller:

[Authorize] // Ensure user is logged in
public class DataController : Controller
{
    private readonly GeneratedClient _client;

    public DataController(GeneratedClient client)
    {
        _client = client; // Token automatically added by AuthorizationHandler
    }

    public async Task<IActionResult> GetUsers()
    {
        try
        {
            // Token is automatically included in the request
            var users = await _client.GetUsersAsync();
            return View(users);
        }
        catch (GeneratedClientException ex)
        {
            if (ex.StatusCode == 401)
            {
                // Token expired, redirect to login
                return RedirectToAction("Login", "Auth");
            }
            return BadRequest(ex.Message);
        }
    }

    public async Task<IActionResult> CreateUser(UserModel model)
    {
        try
        {
            var newUser = await _client.CreateUserAsync(new CreateUserRequest
            {
                Name = model.Name,
                Email = model.Email
            });

            return RedirectToAction("GetUsers");
        }
        catch (GeneratedClientException ex)
        {
            ModelState.AddModelError("", ex.Message);
            return View(model);
        }
    }
}

Scenario C: APIs with Static API Key

Program.cs:

builder.Services.AddHttpClient<GeneratedClient>(client =>
{
    client.DefaultRequestHeaders.Add("X-API-Key", "your-static-api-key");
});

Scenario D: APIs with Basic Authentication

Program.cs:

builder.Services.AddHttpClient<GeneratedClient>(client =>
{
    var credentials = Convert.ToBase64String(
        System.Text.Encoding.ASCII.GetBytes("username:password"));
    client.DefaultRequestHeaders.Authorization =
        new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", credentials);
});

⚙️ Advanced Configuration

Custom Client Settings

ICodeGeneratorAsync generator = CSharpClientFactory.Create();
var configurable = (CodeGeneratorAsync)generator;

configurable.FileName = "MyApiClient.cs";
configurable.IsUseClientInterfaces = true;
configurable.IsGenerateExceptionClass = true;
configurable.IsUseGenerateDto = true;
configurable.IsUseGenerateSyncMethods = false;

await generator.GenerateCSharpClientAsync("https://your-api-url/swagger/v1/swagger.json");

Multiple API Endpoints

// Generate different clients for different APIs
builder.Services.AddHttpClient<AuthClient>(); // For authentication
builder.Services.AddHttpClient<UserClient>().AddHttpMessageHandler<AuthorizationHandler>();
builder.Services.AddHttpClient<OrderClient>().AddHttpMessageHandler<AuthorizationHandler>();

📝 Important Notes

  • Generated clients are placed in the ClientGenerator/ folder
  • Default namespace: GeneratedClients
  • Client naming pattern: {controller}Client
  • Always handle exceptions for better user experience
  • Use [Authorize] attribute on controllers that need authentication
  • Store sensitive tokens in claims, not in session or cookies directly

🔧 Troubleshooting

401 Unauthorized Error:

  • Check if token is properly stored in claims
  • Verify AuthorizationHandler is registered
  • Ensure token hasn't expired

Token Not Being Sent:

  • Verify AddHttpMessageHandler<AuthorizationHandler>() is called
  • Check if IHttpContextAccessor is registered
  • Confirm user is logged in with claims

Need Help?

  • WhatsApp: +918607326044
  • Email: ranjayk693@outlook.com

Happy Coding! 🚀

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  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.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
8.0.0 321 9/17/2025
2.0.0 162 1/29/2025
1.0.0 186 1/28/2025 1.0.0 is deprecated because it is no longer maintained.