
September 19, 2025 08:17 by
Peter
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.
European Best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.
