Getting Started
Architecture
NServiceBus
Transports
Persistence
Hosting
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Modernization
Samples

Using NServiceBus in Azure Functions

This sample shows how to host NServiceBus in an Azure Functions app using the NServiceBus.AzureFunctions.AzureServiceBus package. A Service Bus-triggered function receives messages and dispatches them through the NServiceBus pipeline, while an HTTP-triggered function uses a send-only endpoint to start the conversation.

Prerequisites

Configure connection string

To use the sample, provide a valid Azure Service Bus connection in the local.settings.json file using the default setting name AzureWebJobsServiceBus.

Sample structure

The sample contains the following projects:

  • AzureFunctions.ServiceBus - The Azure Functions host, the NServiceBus endpoint, and the HTTP-triggered sender
  • AzureFunctions.Messages - Message definitions

Running the sample

The Functions project contains two user-authored functions and one generated trigger method:

  1. Orders is the Service Bus-triggered function endpoint.
  2. HttpSender is an HTTP-triggered function that sends a TriggerMessage through a send-only endpoint.
  3. The source generator emits the body for the partial Orders method and forwards incoming messages into NServiceBus.

Running the sample launches the Azure Functions runtime.

To try the sample:

  1. Open a browser and navigate to http://localhost:7071/api/HttpSender. The port number might be different and will be indicated when the function project starts.
  2. The HTTP-triggered function sends a TriggerMessage to the Orders endpoint.
  3. The TriggerMessageHandler processes the message and sends a FollowupMessage.
  4. The FollowupMessageHandler processes the follow-up message.

Code walk-through

The Functions host is configured as follows:

var builder = FunctionsApplication.CreateBuilder(args);

builder.AddNServiceBusFunctions();

var host = builder.Build();
await host.RunAsync();

The endpoint method is defined with [NServiceBusFunction] and configured in ConfigureOrders:

public partial class OrdersEndpoint
{
    [Function("Orders")]
    [NServiceBusFunction]
    public partial Task Orders(
        [ServiceBusTrigger("orders", AutoCompleteMessages = false)]
        ServiceBusReceivedMessage message,
        ServiceBusMessageActions messageActions,
        FunctionContext functionContext,
        CancellationToken cancellationToken = default);

    public static void ConfigureOrders(EndpointConfiguration endpoint)
    {
        endpoint.UseTransport(new AzureServiceBusServerlessTransport(TopicTopology.Default));
        endpoint.UseSerialization<SystemJsonSerializer>();
        endpoint.AddHandler<TriggerMessageHandler>();
        endpoint.AddHandler<FollowupMessageHandler>();
        endpoint.EnableInstallers();
    }
}

The HTTP-triggered sender uses a keyed IMessageSession from the generated send-only endpoint registration:

public class HttpSender([FromKeyedServices("client")] IMessageSession session)
{
    [Function("HttpSender")]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData request)
    {
        await session.Send(new TriggerMessage());

        var response = request.CreateResponse(HttpStatusCode.OK);
        await response.WriteStringAsync("TriggerMessage sent.");
        return response;
    }
}

These are the message handlers:

public class TriggerMessageHandler(ILogger<TriggerMessageHandler> logger) : IHandleMessages<TriggerMessage>
{
    public Task Handle(TriggerMessage message, IMessageHandlerContext context)
    {
        logger.LogWarning("Handling {MessageType} in {HandlerType}", nameof(TriggerMessage), nameof(TriggerMessageHandler));

        return context.SendLocal(new FollowupMessage());
    }
}
public class FollowupMessageHandler(ILogger<FollowupMessageHandler> logger) : IHandleMessages<FollowupMessage>
{
    public Task Handle(FollowupMessage message, IMessageHandlerContext context)
    {
        logger.LogWarning("Handling {MessageType} in {HandlerType}.", nameof(FollowupMessage), nameof(FollowupMessageHandler));

        return Task.CompletedTask;
    }
}

Related Articles