- May 8
Build an Azure Open AI Story Generator with .NET Core
- DevTechie
- AI
Turn a few words into a short story with a single API call. This article walks you through the exact Azure setup you need, explains the .NET Core wrapper API line by line, shows how to test the endpoint with Swagger and Postman, and gives realistic sample requests and outputs . By the end you’ll have a clear path from provisioning Azure OpenAI to returning clean story text to clients.
Step 1: What you must do in Azure
Create an Azure Open AI resource
Provision an Azure Open AI resource in the Azure portal and ensure your subscription has access to the service.Deploy a model and record the deployment name
Deploy the model you want to use and note the deployment name exactly. The code usesgpt-4.1; the string passed toGetChatClientmust match the deployment name in the portal.Copy endpoint and API key
From the resource page, copy the endpoint URL and API key. These values authenticate and route requests.
Below is the screenshot:
Step 2: The .NET Core Wrapper API Explained
Below is a clear, practical walkthrough of the action you provided. Each block explains what the code does and why it matters.
Controller signature and request model
• Endpoint: implemented by api/ImageContent/generateStory
• Request model: should expose a property InputWords (string).
Read configuration:
var endpoint = AzureAIConstants.AzureOpenAIEndpoint;
var key = AzureAIConstants.AzureOpenAIApiKey;Purpose: Read the endpoint and API key.
Create credential and client:
AzureKeyCredential credential = new AzureKeyCredential(key);
AzureOpenAIClient azureClient = new(new Uri(endpoint), credential);
ChatClient chatClient = azureClient.GetChatClient("gpt-4.1");AzureKeyCredential authenticates SDK calls.
• AzureOpenAIClient is the top-level client.
• GetChatClient(“gpt-4.1”) binds the chat client to the named deployment. The deployment name must match the one you created in Azure.
Build messages and prompt:
var messages = new List<ChatMessage>
{
new SystemChatMessage("You are an AI story writer that helps people write a story by a given word."),
new UserChatMessage("generate a story by given topic:" + request.InputWords),
};SystemChatMessage sets the assistant’s role and behavior.
• UserChatMessage contains the user prompt.
• Tip: sanitize and trim and validate length to avoid empty or abusive prompts.
Configure generation options:
var options = new ChatCompletionOptions
{
Temperature = 1f,
MaxOutputTokenCount = 800,
TopP = 1f,
FrequencyPenalty = 0f,
PresencePenalty = 0f
};Temperature controls creativity (higher = more creative).
• MaxOutputTokenCount limits response length and cost.
• TopP, FrequencyPenalty, PresencePenalty further tune output style.
• Recommendation: start with conservative token limits and tune after testing.
Call the model and return result:
ChatCompletion completion = await chatClient.CompleteChatAsync(messages, options);
if (completion != null)
{
return Ok(System.Text.Json.JsonSerializer.Serialize(completion, new JsonSerializerOptions() { WriteIndented = true }));
}
else
{
return Ok("No response received.");
}What happens: the code sends the chat request and serializes the entire object to the client.
Return only the story text example:
var storyText = completion.Choices?.FirstOrDefault()?.Message?.Content;
if (!string.IsNullOrWhiteSpace(storyText))
{
return Ok(new { story = storyText.Trim() });
}
return Ok(new { story = "No response received." });Below is the full code snippet:
[HttpPost("generateStory")]
public async Task<IActionResult> GenerateStory([FromBody] StoryRequest request)
{
// Retrieve the OpenAI endpoint from environment variables
var endpoint = AzureAIConstants.AzureOpenAIEndpoint;
var key =AzureAIConstants.AzureOpenAIApiKey;
AzureKeyCredential credential = new AzureKeyCredential(key);
// Initialize the AzureOpenAIClient
AzureOpenAIClient azureClient = new(new Uri(endpoint), credential);
// Initialize the ChatClient with the specified deployment name
ChatClient chatClient = azureClient.GetChatClient("gpt-4.1");
// Create a list of chat messages
var messages = new List<ChatMessage>
{
new SystemChatMessage(@"You are an AI story writer that helps people write a story by a given word."),
new UserChatMessage(@"generate a story by given topic:"+request.InputWords),
};
// Create chat completion options
var options = new ChatCompletionOptions
{
Temperature = (float)1,
MaxOutputTokenCount = 800,
TopP = (float)1,
FrequencyPenalty = (float)0,
PresencePenalty = (float)0
};
try
{
// Create the chat completion request
ChatCompletion completion = await chatClient.CompleteChatAsync(messages, options);
// Print the response
if (completion != null)
{
return Ok(System.Text.Json.JsonSerializer.Serialize(completion, new JsonSerializerOptions() { WriteIndented = true }));
}
else
{
return Ok("No response received.");
}
}
catch (Exception ex)
{
return BadRequest($"An error occurred: {ex.Message}");
}
}Step 3: Test the API
Here we will create a request in Postman to test our API.
Endpoint : http://localhost:5225/api/ImageContent/generateStory (This will change based on your local settings.)
Request: Here I am just sending below text to generate story out of it :”Anoop(Father) , Neha(Mother) , Aarya(child)”
{
"inputWords": "Anoop(Father) , Neha(Mother) , Aarya(child)"
}Response:
{
"CreatedAt": "2025-11-14T17:39:59+00:00",
"FinishReason": 0,
"ContentTokenLogProbabilities": [],
"RefusalTokenLogProbabilities": [],
"Role": 2,
"Content": [
{
"Kind": 0,
"Text": "Absolutely! Here\u2019s a short story inspired by
Anoop (Father), Neha (Mother), and Aarya (Child):\n\n---\n\n**
A Family Picnic**\n\n
It was a bright Sunday morning.
Anoop woke up before sunrise, smiling as he saw Neha and little Aarya
still fast asleep. He tiptoed to the kitchen,
already excited about the day\u2014they\u2019d planned a family picnic
in the city park.\n\n
As the aroma of freshly brewed chai filled the air,
Neha awoke and joined him, her eyes sparkling. \u201CShall I chop the
veggies for sandwiches?\u201D she whispered.\n\nAarya, only six years old,
soon joined her parents, bouncing up and down in excitement. \u201C
Picnic! Picnic!\u201D she chanted, already clutching her favorite teddy bear.\n\nWith a basket packed with delicious food, the family headed out. In the park, Anoop and Neha watched as Aarya giggled on the swing, her laughter echoing through the cool morning air. Anoop joined Aarya, pushing her gently, while Neha laid out the blanket and opened the basket.\n\nThey feasted together under the shade of an old gulmohar tree, sharing bites and stories. Later, they played cricket with a plastic bat and ball, Aarya racing between her parents, pretending she was a famous cricketer winning the match.\n\nAs the afternoon sun started to dip, Anoop wrapped an arm around Neha, both watching their energetic daughter chase butterflies. They smiled, thankful for these simple moments that stitched their hearts closer together.\n\nOn the way home, Aarya slept in her mother\u2019s lap. Anoop drove, humming softly. The laughter and love of a simple picnic lingered long after the day was done\u2014a gentle reminder that happiness blossoms in togetherness.\n\n---",
"ImageUri": null,
"ImageBytes": null,
"ImageBytesMediaType": null,
"ImageDetailLevel": null,
"Refusal": null
}
],
"ToolCalls": [],
"Refusal": null,
"FunctionCall": null,
"Id": "chatcmpl-Cbs47C8oHez8q95Q4zlzo3IRT1DPi",
"Model": "gpt-4.1-2025-04-14",
"SystemFingerprint": "fp_f99638a8d7",
"Usage": {
"OutputTokenCount": 362,
"InputTokenCount": 50,
"TotalTokenCount": 412,
"OutputTokenDetails": {
"ReasoningTokenCount": 0,
"AudioTokenCount": 0
},
"InputTokenDetails": {
"AudioTokenCount": 0,
"CachedTokenCount": 0
}
}
}Below is the screen shot:

