Skip to main content

Overview

The Azure Functions module enables you to build serverless, event-driven applications using Microsoft Azure Functions. Model your functions in Intent Architect and generate production-ready code that responds to HTTP requests, timers, queues, Cosmos DB changes, and more. Azure Functions is a serverless computing service that enables developers to build and deploy scalable, cost-effective applications without managing infrastructure. Functions automatically scale to handle increased workloads and charge only for actual compute resources used.

Installation

Intent.AzureFunctions

Azure Functions Dispatch

Dispatch patterns for routing requests

Azure Functions OpenAPI

Swagger generation for HTTP triggers

Modeling Functions

You can model Azure Functions in multiple ways within the Services designer:
  • Azure Function - Direct function modeling
  • Commands & Queries - Mark as “Expose as Azure Function”
  • Service Operations - Expose operations as Azure Functions

Trigger Types

HTTP Triggers

HTTP triggers respond to HTTP requests and support RESTful API patterns. Configuration:
  • Set Trigger type to Http Trigger
  • Configure HTTP Settings:
    • Verb: GET, POST, PUT, DELETE, etc.
    • Route: URL path for the endpoint
    • Return Type Mediatype: Response content type
[Function("GetCustomer")]
public async Task<HttpResponseData> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", Route = "customers/{id}")] 
    HttpRequestData req,
    string id,
    CancellationToken cancellationToken)
{
    var customer = await _mediator.Send(new GetCustomerQuery(id), cancellationToken);
    return await req.CreateJsonResponseAsync(customer);
}

Cosmos DB Triggers

Respond to changes in Azure Cosmos DB containers using the change feed. Configuration:
  • Set Trigger to Cosmos DB Trigger
  • Configure:
    • Connection: Connection string name in app settings
    • Database name: Cosmos DB database being monitored
    • Container name: Container being monitored
    • LeaseContainerName: Container for storing leases
    • CreateLeaseContainerIfNotExists: Auto-create lease container
[Function("CustomersCreated")]
public async Task Run(
    [CosmosDBTrigger(
        databaseName: "CosmosDBTriggerTest", 
        containerName: "Customers", 
        Connection = "RepositoryOptions:CosmosConnectionString", 
        CreateLeaseContainerIfNotExists = true, 
        LeaseContainerName = "leases")] 
    IReadOnlyCollection<CustomerCreatedDto> rawCollection,
    CancellationToken cancellationToken)
{
    if (rawCollection == null || rawCollection.Count == 0) return;
    var customers = rawCollection.ToList();
    await _appService.CustomersCreated(customers, cancellationToken);
}
If you model a Command or Service with a non-collection argument, dispatching will be batched, iterating through each item individually.
Learn more: Cosmos DB Triggers

Timer Triggers

Execute functions on a schedule using NCRONTAB expressions. Configuration:
  • Set Trigger to Timer Trigger
  • Schedule Expression: NCRONTAB expression (e.g., 0 */5 * * * * for every 5 minutes)
[Function("DailyCleanup")]
public async Task Run(
    [TimerTrigger("0 0 2 * * *")] TimerInfo myTimer,
    CancellationToken cancellationToken)
{
    await _cleanupService.PerformDailyCleanup(cancellationToken);
}
Learn more: Timer Triggers

Queue Triggers

Process messages from Azure Queue Storage. Configuration:
  • Set Trigger to Queue Trigger
  • Queue Name: Name of the queue to consume
  • Connection: Connection string name in app settings
[Function("CreateCustomer")]
public async Task Run(
    [QueueTrigger("my-queue", Connection = "myconnection")] 
    CreateCustomerCommand createCustomerCommand,
    CancellationToken cancellationToken)
{
    await _mediator.Send(createCustomerCommand, cancellationToken);
}
Message Envelope Access: Check Include Message Envelope to access the underlying QueueMessage:
[Function("CreateCustomer")]
public async Task Run(
    [QueueTrigger("my-queue", Connection = "myconnection")] QueueMessage message,
    CancellationToken cancellationToken)
{
    var command = JsonConvert.DeserializeObject<CreateCustomerCommand>(
        message.Body.ToString())!;
    await _mediator.Send(command, cancellationToken);
}
Queue Output Binding: When a Queue Trigger function has a result, add Queue Output Binding stereotype to write results to another queue: Isolated Process:
[Function("CreateCustomer")]
[QueueOutput("out-queue")]
public async Task<CustomerDto> Run(
    [QueueTrigger("my-queue", Connection = "myconnection")] QueueMessage message,
    CancellationToken cancellationToken)
{
    var command = JsonConvert.DeserializeObject<CreateCustomerCommand>(
        message.Body.ToString())!;
    return await _mediator.Send(command, cancellationToken);
}

Execution Models

The isolated worker process model runs functions in a separate process from the Azure Functions runtime, providing:
  • Better isolation and control
  • Support for .NET 8+
  • More flexibility with dependencies

In-Process (Legacy)

Runs functions in the same process as the Functions host (deprecated for .NET 6+).
Migrate to Isolated Process for new projects. See Migration Guide below.

Module Settings

Simple Function Names

Simplifies [FunctionName] attributes by using operation names instead of full path names. Default: true

Use Global Exception Middleware

Enables a global exception handler for all functions. Default: false

Local Development

Azure Storage Emulator - Azurite

Azurite emulates Azure Storage services locally for development. Installation:
npm install -g azurite
Run:
azurite
Or use the built-in Azurite in Visual Studio 2022+. Configuration:
{
  "AzureWebJobsStorage": "UseDevelopmentStorage=true"
}

Azure Storage Explorer

Browse and interact with Azurite or production storage: Download Azure Storage Explorer

Migrating from In-Process

To migrate from .NET 6 In-Process to Isolated Process:
  1. Open Intent Architect with your application
  2. Manage Modules → Update Intent.AzureFunctions to latest
  3. Visual Studio Designer → Select API host project
  4. Change .NET Version from 6 to 8 (or higher)
  5. Change Output Type to Console (EXE)
  6. Upgrade all C# Projects to .NET 8
  7. Run Software Factory
Result: Startup.cs removed, Program.cs created, all functions updated to Isolated Process model.

Advanced Scenarios

Using Newtonsoft.Json for HTTP Triggers

By default, HTTP triggers use System.Text.Json. To use Newtonsoft.Json:
  1. Add package references:
<ItemGroup>
  <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.23.0" />
  <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
</ItemGroup>
  1. Update AzureFunctionHelper:
[IntentIgnore]
private static readonly Newtonsoft.Json.JsonSerializerSettings SerializationSettings = 
    new() { ContractResolver = new CamelCasePropertyNamesContractResolver() };

[IntentIgnore]
public static async Task<T> DeserializeJsonContentAsync<T>(
    Stream jsonContentStream, 
    CancellationToken cancellationToken)
{
    var requestBody = await new StreamReader(jsonContentStream)
        .ReadToEndAsync(cancellationToken);
    return JsonConvert.DeserializeObject<T>(requestBody) 
        ?? throw new FormatException("Unable to deserialize JSON content.");
}
  1. Configure in Program.cs:
var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((ctx, builder) =>
    {
        builder.Services.AddControllers()
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver = 
                    new CamelCasePropertyNamesContractResolver();
            });
    })
    // ...

Best Practices

  • Use consumption plan for sporadic workloads
  • Consider premium plan for consistent traffic
  • Minimize dependencies and assembly size
  • Use dependency injection efficiently
  • Use Azure Key Vault for secrets
  • Implement proper authorization levels
  • Validate all inputs
  • Use managed identities when possible
  • Enable Application Insights
  • Log structured data
  • Monitor execution time and failures
  • Set up alerts for critical functions
  • Implement retry policies for transient failures
  • Use dead-letter queues for poison messages
  • Log exceptions with context
  • Consider circuit breakers for external dependencies

Resources

Azure Functions Documentation

Official Microsoft documentation

Best Practices

Performance and reliability guidance

Triggers & Bindings

Complete reference for all trigger types

Deployment Guide

Deployment strategies and CI/CD

Build docs developers (and LLMs) love