Getting Started
Architecture
Transports
Persistence
ServiceInsight
ServicePulse
ServiceControl
Monitoring
Samples

Azure Functions with Azure Service Bus (In Process)

Host NServiceBus endpoints with Azure Functions and Azure Service Bus triggers.

Basic usage

Endpoint configuration

NServiceBus can be registered and configured on the host builder using the UseNServiceBus extension method in the startup class:

[assembly: FunctionsStartup(typeof(Startup))]
[assembly: NServiceBusTriggerFunction("MyFunctionsEndpoint")]

class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.UseNServiceBus();
    }
}

Additional configuration settings are retrieved from environment variables. See the configuration section for further details. All configuration settings can also be configured directly via code:

class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.UseNServiceBus(configuration =>
        {
            configuration.Transport.SubscriptionNamingConvention = (name) => name.Replace("X", "Y");
        });
    }
}

Any services registered via the IFunctionsHostBuilder will be available to message handlers via dependency injection. The startup class must be declared via the FunctionStartup attribute: [assembly: FunctionsStartup(typeof(Startup))].

Azure Function queue trigger for NServiceBus

The Azure Function trigger for NServiceBus is auto-generated by specifying the logical endpoint name using a custom assembly attribute:

[assembly: NServiceBusTriggerFunction("MyFunctionsEndpoint")]

The attribute will generate the trigger function required for NServiceBus:

Overriding the trigger function name

The trigger function name is auto-generated by default. To customize the function name, the NServiceBusTriggerFunction attribute can be provided with an additional parameter to set the function name:

[assembly: NServiceBusTriggerFunctionAttribute(EndpointName: "MyFunctionsEndpoint", TriggerFunctionName: "MyTriggerFunction")]

Customizing triggers

The Azure Service Bus trigger can be declared manually instead of relying on the auto-generated trigger. See the article on custom Azure Functions triggers for more information.

Dispatching outside a message handler

Triggering a message using HTTP function:

public class HttpSender
{
    readonly IFunctionEndpoint functionEndpoint;

    public HttpSender(IFunctionEndpoint functionEndpoint)
    {
        this.functionEndpoint = functionEndpoint;
    }

    [FunctionName("HttpSender")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest request, ExecutionContext executionContext, ILogger logger)
    {
        logger.LogInformation("C# HTTP trigger function received a request.");

        var sendOptions = new SendOptions();
        sendOptions.RouteToThisEndpoint();

        await functionEndpoint.Send(new TriggerMessage(), sendOptions, executionContext, logger);

        return new OkObjectResult($"{nameof(TriggerMessage)} sent.");
    }
}

Transport configuration constraints and limitations

The configuration API exposes NServiceBus transport configuration options via the configuration.Transport property to allow customization. However, not all of the options will be applicable for execution within Azure Functions.

Concurrency-related settings are controlled via the Azure Function host.json configuration file. See Concurrency in Azure Functions for details.

Message consistency

NServiceBus can provide transactional consistency between incoming and outgoing messages:

[assembly: NServiceBusTriggerFunction("MyEndpoint", SendsAtomicWithReceive = true)]

This is equivalent to the SendsAtomicWithReceive transport transaction mode. By default, transactional consistency is disabled, providing the same transport guarantees as the ReceiveOnly transport transaction mode.

For more information on configuring message consistency using custom triggers, refer to the custom Azure Functions triggers documentation.

Configuration

ServiceBusTriggeredEndpointConfiguration loads certain configuration values from the Azure Function host environment in the following order:

  • IConfiguration passed in via the constructor
  • Environment variables

ServiceBus connection

When using the NServiceBusTriggerAttribute, the connection to Azure Service Bus can be configured in multiple ways:

  • Using just a <ConnectionName> key, with the value set to the connection string for the ServiceBus namespace to connect to.
  • Using a <CONNECTION_NAME_PREFIX>__fullyQualifiedNamespace along with other connection properties prefixed by the same <CONNECTION_NAME_PREFIX>, as specified in the Identity Based Connections for Azure Functions.

If both a connection string and Identity Based connection values are specified, the connection string will take precedence. The default <ConnectionName> or <CONNECTION_NAME_PREFIX> is AzureWebJobsServiceBus, however an alternate value can be supplied to the Connection property on the NServiceBusTriggerAttribute

Example of a connection string based connection:

{
  "IsEncrypted": false,
  "Values": {
    ...
    "AzureWebJobsServiceBus": "Endpoint=sb://<namespace>.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=<namespace-shared-access-key>",
  }
}

Example of an Identity Based connection:

{
  "IsEncrypted": false,
  "Values": {
    ...
    "MyConnectionName__fullyQualifiedNamespace": "<namespace>.servicebus.windows.net",
    "MyConnectionName__tenantId": "00000000-0000-0000-0000-000000000000",
    "MyConnectionName__clientId": "00000000-0000-0000-0000-000000000000",
    "MyConnectionName__clientSecret": "<client-secret>"
  }
}
[assembly: NServiceBusTriggerFunction("WorkerDemoEndpoint", Connection = "MyConnectionName")]

Other Configuration

KeyValueNotes
ENDPOINT_NAMEThe name of the NServiceBus endpoint to hostA value can be provided directly to the constructor.
NSERVICEBUS_LICENSEThe NServiceBus licenseCan also be provided via serviceBusTriggeredEndpointConfig.EndpointConfiguration.License(...).
WEBSITE_SITE_NAMEThe name of the Azure Function app. Provided when hosting the function in Azure.Used to set the NServiceBus host identifier. Local machine name is used if not set.

For local development, use local.settings.json. In Azure, specify a Function setting using the environment variable as the key.

{
  "IsEncrypted": false,
  "Values": {
    ...
    "NSERVICEBUS_LICENSE": "<?xml version=\"1.0\" encoding=\"utf-8\"?><license id=\"1222e1d1-2222-4a46-b1c6-943c442ca710\" expiration=\"2113-11-30T00:00:00.0000000\" type=\"Standard\" LicenseType=\"Standard\" LicenseVersion=\"4.0\" MaxMessageThroughputPerSecond=\"Max\" WorkerThreads=\"Max\" AllowedNumberOfWorkerNodes=\"Max\">. . .</license>"
  }
}

Custom diagnostics

NServiceBus startup diagnostics are disabled by default when using Azure Functions. Diagnostics can be written to the logs via the following snippet:

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.UseNServiceBus(configuration =>
    {
        configuration.LogDiagnostics();
    });
}

Diagnostics data will be written with logger identification StartupDiagnostics with log level Informational.

Error queue

For recoverability to move the continuously failing messages to the error queue rather than to the Azure Service Bus dead-letter queue, the error queue must be created in advance and configured using the following API:

class EnableDiagnosticsOnStartup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.UseNServiceBus(configuration =>
        {
            configuration.AdvancedConfiguration.SendFailedMessagesTo("error");
        });
    }
}

Preparing the Azure Service Bus namespace

Function endpoints cannot create their own queues or other infrastructure in the Azure Service Bus namespace.

Use the asb-transport command line (CLI) tool to provision the entities in the namespace for the Function endpoint.

Creating the endpoint queue

asb-transport endpoint create <queue name>

See the full documentation for the asb-transport endpoint create command for more details.

Subscribing to events

asb-transport endpoint subscribe <queue name> <eventtype>

See the full documentation for the asb-transport endpoint subscribe command for more details.

Assembly scanning

Assembly scanning loads assemblies from two locations:

  • The bin directory of the Azure Functions application
  • The Azure Functions runtime directory

If the same assembly is present in both locations, an exception is thrown which prevents the endpoint from running. Contact Particular Software support for assistance.

Package requirements

NServiceBus.AzureFunctions.Worker.ServiceBus requires Visual Studio 2019 and .NET SDK version 5.0.300 or higher. Older versions of the .NET SDK might display the following warning which prevents the trigger definition from being auto-generated:

CSC : warning CS8032: An instance of analyzer NServiceBus.AzureFunctions.SourceGenerator.TriggerFunctionGenerator cannot be created from NServiceBus.AzureFunctions.SourceGenerator.dll : Could not load file or assembly 'Microsoft.CodeAnalysis, Version=3.10.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified..

Starting in version 4.1.0 of NServiceBus.AzureFunctions.Worker.ServiceBus and NServiceBus.AzureFunctions.InProcess.ServiceBus , warning CS8032 is treated as an error. To suppress this error, update the project's .csproj file to include the following line in the <PropertyGroup> section at the top:

  <WarningsAsErrors></WarningsAsErrors>

This will revert CS8032 to a warning status so that it does not stop the build process.

Samples

Related Articles