Customization
Extend generated SDKs with partial classes, client hooks, and custom types.
Generated SDKs are designed for extension. All clients and models are partial classes — you can add functionality without modifying generated code.
Partial Class Extensions
Place extension files alongside (not inside) the Generated/ directory:
src/libs/MyApi/
├── Generated/ # Auto-generated — never edit
│ ├── MyApiClient.g.cs
│ └── ...
├── MyApiClient.Auth.cs # Custom auth logic
├── MyApiClient.Helpers.cs # Convenience methods
└── Extensions/
└── ResponseExtensions.csExample extension:
namespace MyCompany.MyApi;
public partial class MyApiClient
{
public async Task<Pet> GetPetByNameAsync(
string name,
CancellationToken cancellationToken = default)
{
var pets = await FindPetsByStatusAsync(
status: FindPetsByStatusStatus.Available,
cancellationToken: cancellationToken);
return pets.First(p => p.Name == name);
}
}Client Hooks
Generated clients expose four partial method hooks for intercepting the HTTP pipeline:
PrepareArguments
Modify parameters before the request is built:
partial void PrepareArguments(HttpClient client, ref string petId)
{
petId = petId.Trim();
}PrepareRequest
Modify the HttpRequestMessage before it's sent:
partial void PrepareRequest(HttpClient client, HttpRequestMessage request,
string url)
{
request.Headers.Add("X-Custom-Header", "value");
}ProcessResponse
Inspect or modify the HttpResponseMessage:
partial void ProcessResponse(HttpClient client,
HttpResponseMessage response)
{
if (response.StatusCode == HttpStatusCode.TooManyRequests)
{
// Log rate limit hit
}
}ProcessResponseContent
Inspect or modify the response body string:
partial void ProcessResponseContent(HttpClient client,
HttpResponseMessage response, ref string content)
{
// Log response for debugging
Console.WriteLine(content);
}Custom Auth
Override the Authorized partial method for non-standard auth:
public partial class MyApiClient
{
partial void Authorized(HttpRequestMessage request)
{
request.Headers.Authorization =
new AuthenticationHeaderValue("Token", _apiKey);
}
}Adding Serializable Types
For NativeAOT/trimming, register custom types with the JSON serializer context:
// JsonSerializerContextTypes.AdditionalTypes.cs
namespace MyCompany.MyApi;
public partial class JsonSerializerContextTypes
{
public MyCustomType? CustomType { get; set; }
}CSharpToJsonSchema Integration
SDKs that support function/tool calling use CSharpToJsonSchema:
[GenerateJsonSchema]
public interface IWeatherTools
{
[Description("Get the current weather for a location")]
public string GetWeather(
[Description("City name")] string city,
[Description("Temperature unit")] string unit = "celsius");
}
// Convert to API tools
var service = new WeatherToolsService();
var tools = service.AsTools();
var calls = service.AsCalls();Inline Spec Patching
Common patterns for fixing specs in generate.sh:
# Remove problematic operations
cat spec.json | jq 'del(.paths["/internal/debug"])' > patched.json
# Rename a schema
cat spec.json | jq '
.components.schemas.NewName = .components.schemas.OldName |
del(.components.schemas.OldName)
' > patched.json
# Inject server URL
cat spec.json | jq '.servers = [{"url": "https://api.example.com"}]' > patched.jsonLast updated on