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
- Rate limits: Azure OpenAI enforces TPM (tokens per minute) limits per deployment. Implement exponential backoff for
429responses. - Token tracking: Log
response.Usage.TotalTokenCountfor cost monitoring — token spend adds up fast. - System prompt: Keep it focused and specific. Vague system messages lead to inconsistent outputs across different model versions.
- Managed Identity: In production replace the API key with
DefaultAzureCredentialfor keyless authentication — no secrets in config.
Conclusion
The Azure OpenAI SDK for .NET is straightforward once you understand the client hierarchy: AzureOpenAIClient → GetChatClient() → 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.