Why combine Minimal APIs and Azure OpenAI?
Imagine a chatbot that can not only answer questions but also trigger real‑world actions such as booking a meeting or fetching the latest weather. Since the release of .NET 8, Minimal APIs let developers expose HTTP endpoints with just a few lines of code, while Azure OpenAI’s function calling feature turns language models into orchestrators for external services. Marrying these two technologies reduces boilerplate, shortens time‑to‑market, and keeps the entire stack inside the familiar C# ecosystem.
Setting up the .NET 8 project
Start with the .NET 8 SDK (released November 2023) on Windows, macOS, or Linux. Create a new web project that targets the minimal‑API template:
dotnet new web -n ChatbotApi --framework net8.0 Navigate into the folder and restore packages. The default project already includes Microsoft.AspNetCore.App, which provides the routing and dependency‑injection infrastructure you need.
Adding Azure OpenAI client
Install the official Azure AI SDK. It bundles the OpenAIClient class that knows how to talk to the Azure OpenAI endpoint.
dotnet add package Azure.AI.OpenAI In Program.cs, register the client as a singleton. Replace YOUR_RESOURCE and YOUR_KEY with the values from the Azure portal.
using Azure.AI.OpenAI; using Azure; var builder = WebApplication.CreateBuilder(args); builder.Services.AddSingleton(new OpenAIClient(new Uri("https://YOUR_RESOURCE.openai.azure.com/"), new AzureKeyCredential("YOUR_KEY"))); var app = builder.Build(); Defining function calls for the chatbot
Function calling works by describing a JSON schema that the model can invoke. For a weather‑lookup scenario, define a function named GetWeather with a single city parameter.
var weatherFunction = new FunctionDefinition( name: "GetWeather", description: "Returns current weather for a given city.", parameters: new Dictionary<string, FunctionParameter> { { "city", new FunctionParameter(type: "string", description: "Name of the city") } } ); When constructing ChatCompletionsOptions, add the function definition and set FunctionCall = "auto". The model will decide whether to call the function based on the user’s request.
Full Minimal API example
The following snippet shows a complete endpoint that receives a user message, forwards it to Azure OpenAI, and, if a function call is returned, executes a mock weather service before responding.
app.MapPost("/chat", async (ChatRequest request, OpenAIClient client) => { var messages = new List<ChatMessage> { new ChatMessage(ChatRole.System, "You are a helpful assistant."), new ChatMessage(ChatRole.User, request.Message) }; var options = new ChatCompletionsOptions(messages) { Functions = { weatherFunction }, FunctionCall = "auto" }; var response = await client.GetChatCompletionsAsync("gpt-4o-mini", options); var choice = response.Value.Choices.First(); if (choice.FinishReason == CompletionsFinishReason.FunctionCall) { var functionCall = choice.Message.FunctionCall; var city = functionCall.Arguments["city"].ToString(); var weather = $"Sunny, 24°C in {city}"; var followUp = new ChatMessage(ChatRole.Assistant, $"Function GetWeather returned: {weather}"); messages.Add(choice.Message); messages.Add(followUp); var finalResponse = await client.GetChatCompletionsAsync("gpt-4o-mini", new ChatCompletionsOptions(messages)); return Results.Ok(new { reply = finalResponse.Value.Choices.First().Message.Content }); } return Results.Ok(new { reply = choice.Message.Content }); }); app.Run(); Notice how the code stays under 60 lines, yet it covers request parsing, function definition, conditional execution, and final response composition—all within the Minimal API paradigm.
Testing the endpoint
Run the application with dotnet run. Use curl or a tool like Postman to send a JSON payload:
curl -X POST http://localhost:5080/chat -H "Content-Type: application/json" -d '{"Message":"What's the weather in Berlin?"}' The response will contain the weather string if the model invoked GetWeather. Inspect the finish_reason field in the raw OpenAI response to verify that function calling occurred.
Performance tips for production
1. Enable HTTP/2 on the Kestrel server to reduce latency when calling Azure OpenAI.
2. Cache frequent function results (e.g., city weather) using MemoryCache with a 5‑minute expiration to avoid unnecessary API calls.
3. Set max_tokens and temperature explicitly in ChatCompletionsOptions to keep costs predictable; a typical chatbot uses 150‑200 tokens per turn and a temperature of 0.7.
4. Deploy to Azure App Service or Azure Container Apps with the “Always On” setting, ensuring the minimal API stays warm during peak traffic.
Sources
- Microsoft Docs – Azure OpenAI Service
- dotnet.microsoft.com – .NET 8 Minimal APIs guide
- OpenAI API reference – Function calling
Author: Mahmut Sarıkaya — sarikayadev.com