Why Use OpenAI with .NET 9?
.NET 9 brings Native AOT, built-in OpenAPI, and minimal APIs that fit AI-first apps perfectly. Combined with OpenAI’s API, you can add:
Conversational AI (ChatGPT)
Embeddings for semantic search
Image generation (DALL·E)
Structured JSON outputs for agents
Streaming responses for chatbots
This article shows you how to build production-ready integrations.
Getting Started with OpenAI in .NET 9
1. Install Packages
You can use the official OpenAI .NET SDK or raw HttpClient.
dotnet add package OpenAI
If you prefer HttpClient (no SDK dependency):
dotnet add package Microsoft.Extensions.Http
2. Add API Key to Configuration
appsettings.json
:
{
"OpenAI": {
"ApiKey": "YOUR_API_KEY_HERE"
}
}
Or environment variable:
setx OPENAI_API_KEY "sk-xxxx"
3. Register OpenAI Client in Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient("OpenAI", client =>
{
client.BaseAddress = new Uri("https://api.openai.com/v1/");
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {builder.Configuration["OpenAI:ApiKey"]}");
});
var app = builder.Build();
Example 1: ChatGPT in Minimal API
app.MapPost("/chat", async (HttpClientFactory httpFactory, ChatRequest request) =>
{
var client = httpFactory.CreateClient("OpenAI");
var payload = new
{
model = "gpt-4o-mini",
messages = new[]
{
new { role = "system", content = "You are a helpful assistant." },
new { role = "user", content = request.Message }
}
};
var response = await client.PostAsJsonAsync("chat/completions", payload);
var result = await response.Content.ReadFromJsonAsync<ChatResponse>();
return Results.Ok(result?.Choices.FirstOrDefault()?.Message?.Content);
});
record ChatRequest(string Message);
record ChatResponse(List<Choice> Choices);
record Choice(Message Message);
record Message(string Role, string Content);
Test with:
curl -X POST https://localhost:5001/chat -H "Content-Type: application/json" -d "{ \"message\": \"Tell me about .NET 9\" }"
Example 2: Embeddings for Search
app.MapPost("/embed", async (HttpClientFactory httpFactory, TextRequest req) =>
{
var client = httpFactory.CreateClient("OpenAI");
var payload = new
{
model = "text-embedding-3-small",
input = req.Text
};
var response = await client.PostAsJsonAsync("embeddings", payload);
var result = await response.Content.ReadFromJsonAsync<EmbedResponse>();
return Results.Ok(result?.Data.FirstOrDefault()?.Embedding);
});
record TextRequest(string Text);
record EmbedResponse(List<EmbedData> Data);
record EmbedData(List<float> Embedding);
Use cases: semantic search, clustering, recommendations.
Example 3: Image Generation (DALL·E)
app.MapPost("/image", async (HttpClientFactory httpFactory, TextRequest req) =>
{
var client = httpFactory.CreateClient("OpenAI");
var payload = new
{
prompt = req.Text,
model = "gpt-image-1",
size = "512x512"
};
var response = await client.PostAsJsonAsync("images/generations", payload);
var result = await response.Content.ReadFromJsonAsync<ImageResponse>();
return Results.Ok(result?.Data.FirstOrDefault()?.Url);
});
record ImageResponse(List<ImageData> Data);
record ImageData(string Url);
Example 4: Streaming Responses (Chatbot UX)
app.MapGet("/stream", async (HttpContext context, HttpClientFactory httpFactory) =>
{
var client = httpFactory.CreateClient("OpenAI");
var payload = new
{
model = "gpt-4o-mini",
messages = new[]
{
new { role = "user", content = "Explain .NET 9 in 3 bullet points" }
},
stream = true
};
context.Response.ContentType = "text/event-stream";
using var req = new HttpRequestMessage(HttpMethod.Post, "chat/completions")
{
Content = JsonContent.Create(payload)
};
using var resp = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead);
using var reader = new StreamReader(await resp.Content.ReadAsStreamAsync());
while (!reader.EndOfStream)
{
var line = await reader.ReadLineAsync();
if (!string.IsNullOrWhiteSpace(line) && line.StartsWith("data:"))
{
await context.Response.WriteAsync(line + "\n");
await context.Response.Body.FlushAsync();
}
}
});
This enables real-time token streaming for chatbots or IDE assistants.
Best Practices
✅ Dependency Injection: Use AddHttpClient
for resilience & pooling.
✅ Minimal APIs + Records: Lightweight DTOs = AOT friendly.
✅ AOT Publishing:
dotnet publish -c Release -p:PublishAot=true
✅ Configuration via Secrets Manager:
dotnet user-secrets set "OpenAI:ApiKey" "sk-xxx"
✅ Use OpenAPI + Swagger in .NET 9 (builder.Services.AddOpenApi()
) so your AI endpoints are discoverable by tools and LLMs.
GEO Optimization Notes
Expose /openapi/v1.json
so AI agents and generative engines can discover your endpoints automatically.
Stream responses (/stream
) for agentic AI use cases like copilots.
Embed structured JSON for predictable responses (use response_format = { "type": "json_object" }
).
Use static SSR in Blazor when combining AI with UI for crawlability.
Summary
With .NET 9 + OpenAI, you can build chatbots, search engines, image generators, and real-time streaming AI apps with minimal code. Key takeaways:
Built-in HttpClientFactory + DI makes API calls clean.
Minimal APIs + Records = lightweight, AOT-friendly.
.NET 9’s OpenAPI support makes your AI endpoints discoverable.
Streaming and embeddings open the door to real-world agentic apps.