Hello! Welcome back to your training for the AZ-204 certification.
In our last lesson, we explored the architecture of Durable Functions. We discussed the key components—Client, Orchestrator, and Activity functions—and the event sourcing mechanism that enables stateful, long-running workflows in a serverless environment.
Today, we'll move from theory to practice. Our goal is to create a basic Durable Functions orchestration demonstrating the function chaining pattern. This is one of the most common and fundamental patterns you'll use. By the end of this lesson, you will have built, run, and tested your first stateful serverless application.
1. The Function Chaining Pattern
As a quick refresher, function chaining is a pattern where you execute a sequence of functions in a specific order. Critically, the output of one function can be passed as the input to the next, allowing you to build a sequential workflow.

Think of it like an assembly line. Each station (an Activity Function) performs a specific task on the product before passing it to the next station. The Orchestrator Function acts as the assembly line's manager, ensuring the product moves through the stations in the correct order.
Your experience designing multi-step processes and service-based architectures will be very relevant here, as we are essentially codifying a distributed workflow.
2. Creating Your First Durable Functions Project
Let's start by creating the project in Visual Studio. We will use the built-in template, which provides the basic scaffolding for a Durable Function app, including the client, orchestrator, and activity functions we discussed previously.
The following quickstart guide from Microsoft Learn will walk you through creating the project. Since you use Visual Studio 2022, please focus on that section of the guide.
Quickstart: Create a C# Durable Functions app
This guide provides step-by-step instructions for creating a new Durable Functions project in Visual Studio. Follow the steps under the 'Visual Studio 2022' tab.
Follow the instructions in the 'Create a function app project' section under the 'Visual Studio 2022' tab. Stop when you reach the 'Test the function locally' section. Pay close attention to selecting the '.NET 8 Isolated' worker and the 'Durable Functions Orchestration' template. Ensure the 'Use Azurite' option is checked, as this sets up the local storage emulator we need.
After completing these steps, you will have a project with a file named Function1.cs (or similar). This file contains the three essential function types:
RunOrchestrator: The orchestrator function, decorated with[Function("Function1")]and taking anOrchestrationContext.SayHello: The activity function, decorated with[Function("SayHello")]and taking anActivityTrigger.HttpStart: The client function, decorated with[Function("Function1_HttpStart")]and using anHttpTriggerto start the orchestration.
This structure should look familiar from our last lesson. The template has given us a working, albeit simple, function chain that calls the SayHello activity three times.
3. Implementing a Custom Function Chain
Now, let's modify this boilerplate code to create a more descriptive and practical function chain. We will build a simple financial transaction workflow. The logic will be:
- Get cash from an ATM.
- Use the cash to buy groceries.
- Deposit the remaining money back into the bank.
This example is great because it's a clear, sequential process. We'll use a video tutorial to guide us through modifying the code and running it.
Durable Functions Tutorial Using C# | Azure Activity Functions | Stateful Functions
This video provides a clear, practical demonstration of modifying the default Durable Function template to implement a custom function chain. The presenter's step-by-step approach is easy to follow.
Watch the video from 10:41 to 19:43. Follow along in your own Visual Studio project. (10:41 - 14:20) First, understand the three default functions the presenter explains. This is a review of what the template created. (14:20 - 19:43) This is the core part. Modify your code as the presenter does. Instead of just one SayHello activity, you will create three distinct activity functions (GetCash, BuyGrocery, DepositMoney). Then, update the orchestrator function (RunOrchestrator) to call these new activities in sequence using CallActivityAsync.
Let's review the code for the orchestrator function, which is the core of the chain. It should look something like this, based on the video's logic.
[Function("Function1")] // This is the Orchestrator
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
ILogger logger = context.CreateReplaySafeLogger(nameof(Function1));
logger.LogInformation("Saying hello.");
var outputs = new List<string>();
// The function chain:
// 1. Call the GetCash activity
outputs.Add(await context.CallActivityAsync<string>("GetCash", "200"));
// 2. Call the BuyGrocery activity
outputs.Add(await context.CallActivityAsync<string>("BuyGrocery", "Potato"));
// 3. Call the DepositMoney activity
outputs.Add(await context.CallActivityAsync<string>("DepositMoney", "Citibank"));
return outputs;
}
And one of the new activity functions would be:
[Function("GetCash")] // This is an Activity
public static string GetCash([ActivityTrigger] string amount, FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger("GetCash");
logger.LogInformation("Withdrawing {amount}", amount);
return $"Cash {amount} withdrawn.";
}
Notice how the RunOrchestrator function contains the workflow logic, calling each activity with await context.CallActivityAsync. This C# code cleanly describes a complex, distributed process, and the Durable Functions framework handles all the underlying state management and reliability.
For an official reference on the C# syntax, you can consult the Microsoft Learn documentation on function chaining.
Function chaining - Azure Durable - Microsoft Learn
This document provides the authoritative code examples for the function chaining pattern in C#.
Briefly review the C# code snippets for the 'Orchestrator' and 'Activity' functions. Note the use of [OrchestrationTrigger] with IDurableOrchestrationContext (in-process model) or TaskOrchestrationContext (isolated model), and [ActivityTrigger]. This reinforces the code structure you just implemented.
4. Running and Testing the Orchestration Locally
With the code in place, it's time to run it and see the result. You'll start the function app locally, which will also start the Azurite storage emulator to manage the orchestration's state. Then, you'll use an HTTP tool like Postman to trigger the workflow and check its status.
Your background with C#, Visual Studio, and REST APIs will make this process feel very familiar.
Let's return to the video tutorial, which provides an excellent walkthrough of the local testing process.
Durable Functions Tutorial Using C# | Azure Activity Functions | Stateful Functions
This final video segment demonstrates how to run your Durable Function locally, trigger it using Postman, and check the status to see the final output of your function chain.
Watch from 19:43 to 23:22. Run the project in Visual Studio by pressing F5. Note the URL for the HTTP starter function that appears in the console. Use Postman (or another tool) to send a POST request to that URL to start the orchestration. Examine the JSON response. Copy the URL from the statusQueryGetUri field. Send a GET request to this status URL to see the orchestration status and the final output array containing the results from your chained activities.
When you query the status URL, the runtimeStatus should be "Completed," and the output field should contain an array of the strings returned by your three activity functions, proving that the chain executed successfully.
Conclusion
Congratulations! You have successfully built and run your first stateful serverless workflow using Durable Functions. You've applied the architectural concepts from the previous lesson to a hands-on exercise, creating a sequence of functions that pass data and execute in a specific order.
Key Takeaways:
- The "Durable Functions Orchestration" template in Visual Studio provides the necessary client, orchestrator, and activity functions to get started quickly.
- You implement a function chain by making a series of
await context.CallActivityAsync<T>()calls within an orchestrator function. - The orchestrator defines the what and when of the workflow, while the activity functions do the actual work.
- You can test orchestrations locally using the storage emulator (Azurite) and an HTTP client to trigger the workflow and poll for its status.
Next Steps
Function chaining is powerful for sequential processes. But what if you need to perform many independent tasks at once and wait for them all to finish? In our next lesson, we will tackle another common durable pattern by learning to implement the fan-out/fan-in pattern in a Durable Functions orchestration. This will allow you to execute activities in parallel, dramatically improving performance for certain types of workflows.