Skip to main content

Azure OpenAI with C#: Integrate GPT-4o in .NET

Learn how to integrate Azure OpenAI GPT-4o into your C# .NET application with runnable code, streaming, and best practices. Start building AI apps today.

If you want to add generative AI to your enterprise apps, learning Azure OpenAI with C# is one of the highest-value skills you can pick up in 2026. Azure OpenAI gives you the same GPT-4o models that power ChatGPT, but wrapped in Microsoft's security, compliance, and regional data guarantees — a combination that enterprise .NET teams in the USA, UK, Canada, and Australia increasingly require. In this tutorial you'll learn how to integrate GPT-4o into your .NET application using the official Azure SDK, complete with runnable code, streaming responses, and production best practices.

By the end, you'll understand not just how to call the API, but why each configuration choice matters for cost, latency, and reliability.

Why Use Azure OpenAI with C# Instead of the Public OpenAI API?

Both services expose GPT-4o, so why do so many .NET shops search for Azure OpenAI C# specifically? The reasons are architectural:

  • Data residency & compliance — Azure OpenAI keeps your prompts and completions inside your chosen Azure region. For teams bound by HIPAA, GDPR, or SOC 2, this is often a hard requirement.
  • Entra ID (Azure AD) authentication — you can authenticate with managed identities instead of raw API keys, eliminating a whole class of secret-leak incidents.
  • Enterprise SLAs and quotas — provisioned throughput units (PTUs) give you predictable latency under load, which the public API's shared pool cannot guarantee.
  • Native .NET tooling — the Azure.AI.OpenAI package integrates cleanly with dependency injection, IHttpClientFactory, and the rest of the ASP.NET Core ecosystem.

If you're building an internal tool or a customer-facing SaaS on .NET, Azure OpenAI is usually the right call.

Prerequisites for This Azure OpenAI C# Tutorial

Before writing any code, make sure you have:

  • An Azure subscription with access to Azure OpenAI (request access via the Azure portal if you haven't already).
  • A deployed GPT-4o model. In the Azure AI Foundry portal, create a deployment and note the deployment name — this is not the same as the model name.
  • The endpoint URL (e.g. https://your-resource.openai.azure.com/) and an API key from the resource's Keys and Endpoint blade.
  • .NET 8 or later installed.

Installing the Azure OpenAI SDK for C#

Create a new console app and add the official package. The 2.x line of Azure.AI.OpenAI is built on top of the official OpenAI .NET library, so the API surface is modern and consistent.

dotnet new console -n GptDemo
cd GptDemo
dotnet add package Azure.AI.OpenAI
dotnet add package Azure.Identity

How to Call GPT-4o from C#: Your First Chat Completion

Here's the minimal working example. It creates a client, sends a system and user message, and prints the model's reply.

using Azure.AI.OpenAI;
using OpenAI.Chat;
using System.ClientModel;

string endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")!;
string apiKey   = Environment.GetEnvironmentVariable("AZURE_OPENAI_KEY")!;
string deployment = "gpt-4o"; // your deployment name

AzureOpenAIClient azureClient = new(
    new Uri(endpoint),
    new ApiKeyCredential(apiKey));

ChatClient chatClient = azureClient.GetChatClient(deployment);

ChatCompletion completion = await chatClient.CompleteChatAsync(
    new SystemChatMessage("You are a concise C# expert."),
    new UserChatMessage("Explain async/await in one sentence."));

Console.WriteLine(completion.Content[0].Text);

Notice the two-package split: Azure.AI.OpenAI gives you AzureOpenAIClient, while the message and completion types (ChatClient, UserChatMessage) come from the underlying OpenAI.Chat namespace. This is a common source of confusion for newcomers — you need using directives for both.

Why Use Environment Variables Instead of Hardcoding Keys?

Never commit API keys to source control. Reading from environment variables (or better, Azure Key Vault) keeps secrets out of your repository and lets you rotate keys without redeploying. In production, prefer the keyless approach below.

Best Practice: Authenticate with Entra ID Instead of API Keys

The single most impactful security upgrade for an Azure OpenAI C# app is to drop API keys entirely and use DefaultAzureCredential. This uses your managed identity in Azure and your developer credentials locally — no secrets anywhere.

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

AzureOpenAIClient azureClient = new(
    new Uri(endpoint),
    new DefaultAzureCredential());

ChatClient chatClient = azureClient.GetChatClient("gpt-4o");

Assign the Cognitive Services OpenAI User role to your identity, and the SDK handles token acquisition and refresh automatically. This is the recommended pattern for any production deployment.

Streaming GPT-4o Responses in C# for a ChatGPT-Like Experience

Waiting several seconds for a full response feels sluggish. Streaming lets you display tokens as they're generated — exactly how ChatGPT feels. Use CompleteChatStreamingAsync and iterate with await foreach.

await foreach (StreamingChatCompletionUpdate update
    in chatClient.CompleteChatStreamingAsync(
        new UserChatMessage("Write a haiku about C# and AI.")))
{
    foreach (ChatMessageContentPart part in update.ContentUpdate)
    {
        Console.Write(part.Text);
    }
}
Console.WriteLine();

Why streaming matters: beyond perceived speed, streaming lets you cancel a runaway generation early (saving tokens and money) and start post-processing before the model finishes. For chat UIs and copilots, it's essentially mandatory.

Controlling Cost and Quality: Key Chat Options

GPT-4o billing is per token, so how you configure a request directly affects your Azure bill. Use ChatCompletionOptions to tune behavior:

var options = new ChatCompletionOptions
{
    MaxOutputTokenCount = 400,   // hard cap on response length & cost
    Temperature = 0.3f,          // lower = more deterministic
    TopP = 1.0f
};

ChatCompletion completion = await chatClient.CompleteChatAsync(
    new[] { new UserChatMessage("Summarize the SOLID principles.") },
    options);

Console.WriteLine($"Prompt tokens: {completion.Usage.InputTokenCount}");
Console.WriteLine($"Output tokens: {completion.Usage.OutputTokenCount}");
  • MaxOutputTokenCount is your safety valve. Without it, a verbose model can generate thousands of unexpected tokens.
  • Temperature near 0 is best for factual, repeatable tasks (data extraction, classification); higher values (0.7–1.0) suit creative writing.
  • Usage reporting lets you log real token consumption for cost monitoring and chargebacks.

Advanced Azure OpenAI in C#: Tool Calling (Function Calling)

Senior developers searching for advanced Azure OpenAI C# techniques usually want tool calling — letting GPT-4o invoke your own functions to fetch live data. Define a tool, and the model decides when to call it.

ChatTool getWeatherTool = ChatTool.CreateFunctionTool(
    functionName: "get_weather",
    functionDescription: "Get the current weather for a city",
    functionParameters: BinaryData.FromString("""
    {
      "type": "object",
      "properties": {
        "city": { "type": "string", "description": "City name" }
      },
      "required": ["city"]
    }
    """));

var options = new ChatCompletionOptions();
options.Tools.Add(getWeatherTool);

ChatCompletion completion = await chatClient.CompleteChatAsync(
    new[] { new UserChatMessage("What's the weather in London?") },
    options);

if (completion.FinishReason == ChatFinishReason.ToolCalls)
{
    foreach (ChatToolCall call in completion.ToolCalls)
    {
        Console.WriteLine($"Model wants to call: {call.FunctionName}");
        Console.WriteLine($"With arguments: {call.FunctionArguments}");
        // Execute your real function, then send the result back as a
        // ToolChatMessage in a follow-up CompleteChatAsync call.
    }
}

The pattern is a loop: the model requests a tool call, your code executes it, you send the result back as a ToolChatMessage, and the model produces a final natural-language answer. This is the foundation of AI agents and Retrieval-Augmented Generation (RAG) systems.

Registering the Client with Dependency Injection in ASP.NET Core

In a real .NET web app, don't create a new client per request. Register a single AzureOpenAIClient as a singleton — it's thread-safe and manages its own connection pooling.

builder.Services.AddSingleton(sp =>
    new AzureOpenAIClient(
        new Uri(builder.Configuration["AzureOpenAI:Endpoint"]!),
        new DefaultAzureCredential()));

// Inject it into a controller or minimal API:
app.MapPost("/ask", async (AzureOpenAIClient client, string prompt) =>
{
    ChatClient chat = client.GetChatClient("gpt-4o");
    ChatCompletion result = await chat.CompleteChatAsync(
        new UserChatMessage(prompt));
    return Results.Ok(result.Content[0].Text);
});

Common Pitfalls When Integrating GPT-4o into .NET

  • Confusing model name with deployment name — the SDK expects the deployment name you chose in Azure, which may differ from gpt-4o.
  • Ignoring rate limits (HTTP 429) — the SDK retries transiently, but under sustained load you must implement backoff and consider provisioned throughput. Always wrap calls in try/catch for RequestFailedException.
  • Forgetting to cap output tokens — unbounded responses inflate cost and latency.
  • Sending unbounded conversation history — every past message re-bills as input tokens. Trim or summarize old turns.
  • Leaking API keys — use Entra ID and Key Vault, not hardcoded strings.
  • No content filtering handling — Azure OpenAI applies content filters; handle the case where a response is filtered rather than assuming success.

Conclusion: Key Takeaways for Azure OpenAI with C#

Integrating Azure OpenAI with C# is remarkably approachable once you understand the moving parts. To recap the essentials:

  • Use the Azure.AI.OpenAI package and get a ChatClient from your AzureOpenAIClient.
  • Authenticate with Entra ID and DefaultAzureCredential in production — skip API keys.
  • Stream responses for a responsive, ChatGPT-like UX.
  • Control cost with MaxOutputTokenCount, tuned Temperature, and token-usage logging.
  • Unlock advanced scenarios like agents and RAG with tool calling.
  • Register the client as a singleton and watch out for the common pitfalls above.

With these patterns, you can confidently ship GPT-4o features in your .NET applications — secure, cost-aware, and production-ready. Start with the simple chat completion example, then layer in streaming and tool calling as your requirements grow. Happy coding!

About csharp-coder.com
Your go-to resource for C#, .NET, and modern software development. Follow along for daily tutorials, tips, and real-world examples.

Comments

Popular posts from this blog

Angular 14 : 404 error during refresh page after deployment

In this article, We will learn how to solve 404 file or directory not found angular error in production.  Refresh browser angular 404 file or directory not found error You have built an Angular app and created a production build with ng build --prod You deploy it to a production server. Everything works fine until you refresh the page. The app throws The requested URL was not found on this server message (Status code 404 not found). It appears that angular routing not working on the production server when you refresh the page. The error appears on the following scenarios When you type the URL directly in the address bar. When you refresh the page The error appears on all the pages except the root page.   Reason for the requested URL was not found on this server error In a Multi-page web application, every time the application needs to display a page it has to send a request to the web server. You can do that by either typing the URL in the address bar, clicking on the Me...

Angular 14 CRUD Operation with Web API .Net 6.0

How to Perform CRUD Operation Using Angular 14 In this article, we will learn the angular crud (create, read, update, delete) tutorial with ASP.NET Core 6 web API. We will use the SQL Server database and responsive user interface for our Web app, we will use the Bootstrap 5. Let's start step by step. Step 1 - Create Database and Web API First we need to create Employee database in SQL Server and web API to communicate with database. so you can use my previous article CRUD operations in web API using net 6.0 to create web API step by step. As you can see, after creating all the required API and database, our API creation part is completed. Now we have to do the angular part like installing angular CLI, creating angular 14 project, command for building and running angular application...etc. Step 2 - Install Angular CLI Now we have to install angular CLI into our system. If you have already installed angular CLI into your system then skip this step.  To install angular CLI ope...

Send an Email via SMTP with MailKit Using .NET 6

How to Send an Email in .NET Core This tutorial show you how to send an email in .NET 6.0 using the MailKit email client library. Install MailKit via NuGet Visual Studio Package Manager Console: Install-Package MailKit How to Send an HTML Email in .NET 6.0 This code sends a simple HTML email using the Gmail SMTP service. There are instructions further below on how to use a few other popular SMTP providers - Gmail, Hotmail, Office 365. // create email message var email = new MimeMessage(); email.From.Add(MailboxAddress.Parse("from_address@example.com")); email.To.Add(MailboxAddress.Parse("to_address@example.com")); email.Subject = "Email Subject"; email.Body = new TextPart(TextFormat.Html) { Text = "<h1>Test HTML Message Body</h1>" }; // send email using var smtp = new SmtpClient(); smtp.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTls); smtp.Authenticate("[Username]", "[Password]"); smtp.Se...