ASP.NET Core  

How to Use OpenAI in .NET 9: Complete Guide with Code Examples

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.