Building AI-Powered Apps with .NET 8 and Azure OpenAI

Azure OpenAI brings GPT-4 directly into your .NET ecosystem. In this article we set up the official SDK, make chat completion calls, and handle streaming — all inside a clean .NET 8 service.

Why Azure OpenAI in .NET?

As a .NET developer you likely already have infrastructure in Azure. Azure OpenAI integrates naturally with your existing setup — managed identity, Azure Key Vault for secrets, and familiar SDK patterns. It gives you the same GPT models as OpenAI's API, but within your own Azure subscription with enterprise-grade security and compliance.

Setting Up

Install the official NuGet package:

dotnet add package Azure.AI.OpenAI

You'll need your Azure OpenAI endpoint and API key from the Azure portal. Store these in appsettings.json or, better, in Azure Key Vault:

{
  "AzureOpenAI": {
    "Endpoint": "https://your-resource.openai.azure.com/",
    "ApiKey": "your-api-key",
    "DeploymentName": "gpt-4o"
  }
}

Chat Completion Example

Here's a minimal service that sends a message and returns the response:

using Azure;
using Azure.AI.OpenAI;
using OpenAI.Chat;

public class AiService
{
    private readonly ChatClient _client;

    public AiService(IConfiguration config)
    {
        var endpoint  = new Uri(config["AzureOpenAI:Endpoint"]!);
        var apiKey    = new AzureKeyCredential(config["AzureOpenAI:ApiKey"]!);
        var deployment = config["AzureOpenAI:DeploymentName"]!;

        var azureClient = new AzureOpenAIClient(endpoint, apiKey);
        _client = azureClient.GetChatClient(deployment);
    }

    public async Task<string> AskAsync(string userMessage)
    {
        var messages = new List<ChatMessage>
        {
            new SystemChatMessage("You are a helpful assistant."),
            new UserChatMessage(userMessage)
        };

        ChatCompletion response = await _client.CompleteChatAsync(messages);
        return response.Content[0].Text;
    }
}

Streaming Responses

For longer responses, streaming displays text as it arrives — much better UX than waiting for the full answer:

public async IAsyncEnumerable<string> AskStreamAsync(string userMessage)
{
    var messages = new List<ChatMessage>
    {
        new SystemChatMessage("You are a helpful assistant."),
        new UserChatMessage(userMessage)
    };

    await foreach (StreamingChatCompletionUpdate update
        in _client.CompleteChatStreamingAsync(messages))
    {
        foreach (ChatMessageContentPart part in update.ContentUpdate)
        {
            if (!string.IsNullOrEmpty(part.Text))
                yield return part.Text;
        }
    }
}

In a Blazor app, bind the output to a string and call StateHasChanged() on each token — real-time streaming chat, no SignalR needed.

Key Considerations

Conclusion

The Azure OpenAI SDK for .NET is straightforward once you understand the client hierarchy: AzureOpenAIClientGetChatClient()CompleteChatAsync(). Streaming is first-class through async enumerable, which fits naturally with existing .NET patterns. Start with basic completions, layer in streaming for UX, and secure credentials with managed identity before going to production.