Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Includes:
Hosting integration not
Client integration
Azure SignalR Service is a fully managed real-time messaging service that simplifies adding real-time web functionality to your applications. The .NET Aspire Azure SignalR Service integration enables you to easily provision, configure, and connect your .NET applications to Azure SignalR Service instances.
This article describes how to integrate Azure SignalR Service into your .NET Aspire applications, covering both hosting and client integration.
Hosting integration
The .NET Aspire Azure SignalR Service hosting integration models Azure SignalR resources as the following types:
- AzureSignalRResource: Represents an Azure SignalR Service resource, including connection information to the underlying Azure resource.
- AzureSignalREmulatorResource: Represents an emulator for Azure SignalR Service, allowing local development and testing without requiring an Azure subscription.
To access the hosting types and APIs for expressing these resources in the distributed application builder, install the 📦 Aspire.Hosting.Azure.SignalR NuGet package in your app host project:
dotnet add package Aspire.Hosting.Azure.SignalR
For more information, see dotnet add package or Manage package dependencies in .NET applications.
Add an Azure SignalR Service resource
To add an Azure SignalR Service resource to your app host project, call the AddAzureSignalR method:
var builder = DistributedApplication.CreateBuilder(args);
var signalR = builder.AddAzureSignalR("signalr");
var api = builder.AddProject<Projects.ApiService>("api")
.WithReference(signalR)
.WaitFor(signalR);
builder.AddProject<Projects.WebApp>("webapp")
.WithReference(api)
.WaitFor(api);
// Continue configuring and run the app...
In the preceding example:
- An Azure SignalR Service resource named
signalr
is added. - The
signalr
resource is referenced by theapi
project. - The
api
project is referenced by thewebapp
project.
This architecture allows the webapp
project to communicate with the api
project, which in turn communicates with the Azure SignalR Service resource.
Important
Calling AddAzureSignalR
implicitly enables Azure provisioning support. Ensure your app host is configured with the appropriate Azure subscription and location. For more information, see Local provisioning: Configuration.
Provisioning-generated Bicep
When you add an Azure SignalR Service resource, .NET Aspire generates provisioning infrastructure using Bicep. The generated Bicep includes defaults for location, SKU, and role assignments:
@description('The location for the resource(s) to be deployed.')
param location string = resourceGroup().location
resource signalr 'Microsoft.SignalRService/signalR@2024-03-01' = {
name: take('signalr-${uniqueString(resourceGroup().id)}', 63)
location: location
properties: {
cors: {
allowedOrigins: [
'*'
]
}
features: [
{
flag: 'ServiceMode'
value: 'Default'
}
]
}
kind: 'SignalR'
sku: {
name: 'Free_F1'
capacity: 1
}
tags: {
'aspire-resource-name': 'signalr'
}
}
output hostName string = signalr.properties.hostName
output name string = signalr.name
The generated Bicep provides a starting point and can be customized further.
Customize provisioning infrastructure
All .NET Aspire Azure resources are subclasses of the AzureProvisioningResource type. This enables customization of the generated Bicep by providing a fluent API to configure the Azure resources using the ConfigureInfrastructure<T>(IResourceBuilder<T>, Action<AzureResourceInfrastructure>) API:
builder.AddAzureSignalR("signalr")
.ConfigureInfrastructure(infra =>
{
var signalRService = infra.GetProvisionableResources()
.OfType<SignalRService>()
.Single();
signalRService.Sku.Name = "Premium_P1";
signalRService.Sku.Capacity = 10;
signalRService.PublicNetworkAccess = "Enabled";
signalRService.Tags.Add("ExampleKey", "Example value");
});
The preceding code:
- Chains a call to the ConfigureInfrastructure API:
- The
infra
parameter is an instance of the AzureResourceInfrastructure type. - The provisionable resources are retrieved by calling the GetProvisionableResources() method.
- The single SignalRService resource is retrieved.
- The SignalRService.Sku property is assigned a name of
Premium_P1
and a capacity of10
. - The SignalRService.PublicNetworkAccess property is set to
Enabled
. - A tag is added to the SignalR service resource with a key of
ExampleKey
and a value ofExample value
.
- The
Connect to an existing Azure SignalR Service
You might have an existing Azure SignalR Service that you want to connect to. You can chain a call to annotate that your AzureSignalRResource is an existing resource:
var builder = DistributedApplication.CreateBuilder(args);
var existingSignalRName = builder.AddParameter("existingSignalRName");
var existingSignalRResourceGroup = builder.AddParameter("existingSignalRResourceGroup");
var signalr = builder.AddAzureSignalR("signalr")
.AsExisting(existingSignalRName, existingSignalRResourceGroup);
builder.AddProject<Projects.ExampleProject>()
.WithReference(signalr);
// After adding all resources, run the app...
For more information on treating Azure SignalR resources as existing resources, see Use existing Azure resources.
Alternatively, instead of representing an Azure SignalR resource, you can add a connection string to the app host. Which is a weakly-typed approach that's based solely on a string
value. To add a connection to an existing Azure SignalR Service, call the AddConnectionString method:
var builder = DistributedApplication.CreateBuilder(args);
var signalr = builder.ExecutionContext.IsPublishMode
? builder.AddAzureSignalR("signalr")
: builder.AddConnectionString("signalr");
builder.AddProject<Projects.ApiService>("apiService")
.WithReference(signalr);
Note
Connection strings are used to represent a wide range of connection information, including database connections, message brokers, endpoint URIs, and other services. In .NET Aspire nomenclature, the term "connection string" is used to represent any kind of connection information.
The connection string is configured in the app host's configuration, typically under User Secrets, under the ConnectionStrings
section:
{
"ConnectionStrings": {
"signalr": "Endpoint=https://your-signalr-instance.service.signalr.net;AccessKey=your-access-key;Version=1.0;"
}
}
For more information, see Add existing Azure resources with connection strings.
Add an Azure SignalR Service emulator resource
The Azure SignalR Service emulator is a local development and testing tool that emulates the behavior of Azure SignalR Service. This emulator only supports Serverless mode, which requires a specific configuration when using the emulator.
To use the emulator, chain a call to the RunAsEmulator(IResourceBuilder<AzureSignalRResource>, Action<IResourceBuilder<AzureSignalREmulatorResource>>) method:
using Aspire.Hosting.Azure;
var builder = DistributedApplication.CreateBuilder(args);
var signalR = builder.AddAzureSignalR("signalr", AzureSignalRServiceMode.Serverless)
.RunAsEmulator();
builder.AddProject<Projects.ApiService>("apiService")
.WithReference(signalR)
.WaitFor(signalR);
// After adding all resources, run the app...
In the preceding example, the RunAsEmulator
method configures the Azure SignalR Service resource to run as an emulator. The emulator is based on the mcr.microsoft.com/signalr/signalr-emulator:latest
container image. The emulator is started when the app host is run, and is stopped when the app host is stopped.
Azure SignalR Service modes
While the Azure SignalR Service emulator only supports the Serverless mode, the Azure SignalR Service resource can be configured to use either of the following modes:
AzureSignalRServiceMode.Default
AzureSignalRServiceMode.Serverless
The Default mode is the "default" configuration for Azure SignalR Service. Each mode has its own set of features and limitations. For more information, see Azure SignalR Service modes.
Important
The Azure SignalR Service emulator only works in Serverless mode and the AddNamedAzureSignalR
method doesn't support Serverless mode.
Hub host integration
There isn't an official .NET Aspire Azure SignalR client integration. However, there is limited support for similar experiences. In these scenarios, the Azure SignalR Service acts as a proxy between the server (where the Hub or Hub<T> are hosted) and the client (where the SignalR client is hosted). The Azure SignalR Service routes traffic between the server and client, allowing for real-time communication.
Important
It's important to disambiguate between .NET Aspire client integrations and the .NET SignalR client. SignalR exposes hubs—which act as a server-side concept—and SignalR clients connect to those hubs. The .NET projects that host SignalR hubs are where you integrate with .NET Aspire. The SignalR client is a separate library that connects to those hubs, in a different project.
There are two packages available for, each with addressing specific scenarios such as managing the client connection to Azure SignalR Service, and hooking up to the Azure SignalR Service resource. To get started, install the 📦 Microsoft.Azure.SignalR NuGet package in the project hosting your SignalR hub.
dotnet add package Microsoft.Azure.SignalR
Configure named Azure SignalR Service in Default mode
In Default mode, your consuming project needs to rely on a named Azure SignalR Service resource. Consider the following diagram that illustrates the architecture of Azure SignalR Service in Default mode:
For more information on Default mode, see Azure SignalR Service: Default mode.
In your SignalR hub host project, configure Azure SignalR Service by chaining calls to .AddSignalR().AddNamedAzureSignalR("name")
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSignalR()
.AddNamedAzureSignalR("signalr");
var app = builder.Build();
app.MapHub<ChatHub>("/chat");
app.Run();
The AddNamedAzureSignalR
method configures the project to use the Azure SignalR Service resource named signalr
. The connection string is read from the configuration key ConnectionStrings:signalr
, and additional settings are loaded from the Azure:SignalR:signalr
configuration section.
Note
If you're using the Azure SignalR emulator, you cannot use the AddNamedAzureSignalR
method.
Configure Azure SignalR Service in Serverless mode
If you're app host is using the Azure SignalR emulator, you'll also need to install the 📦 Microsoft.Azure.SignalR.Management NuGet package.
dotnet add package Microsoft.Azure.SignalR.Management
Azure SignalR Serverless mode doesn't require a hub server to be running. The Azure SignalR Service is responsible for maintaining client connections. Additionally, in this mode, you cannot use traditional SignalR Hubs, such as Hub, Hub<T>, or IHubContext<THub>. Instead, configure an upstream endpoint which is usually an Azure Function SignalR trigger. Consider the following diagram that illustrates the architecture of Azure SignalR Service in Serverless mode:
For more information on Serverless mode, see Azure SignalR Service: Serverless mode.
In a project that's intended to communicate with the Azure SignalR Service, register the appropriate services by calling AddSignalR and then registering the ServiceManager
using the signalr
connection string and add a /negotiate
endpoint:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton(sp =>
{
return new ServiceManagerBuilder()
.WithOptions(options =>
{
options.ConnectionString = builder.Configuration.GetConnectionString("signalr");
})
.BuildServiceManager();
});
var app = builder.Build();
app.MapPost("/negotiate", async (string? userId, ServiceManager sm, CancellationToken token) =>
{
// The creation of the ServiceHubContext is expensive, so it's recommended to
// only create it once per named context / per app run if possible.
var context = await sm.CreateHubContextAsync("messages", token);
var negotiateResponse = await context.NegotiateAsync(new NegotiationOptions
{
UserId = userId
}, token);
// The JSON serializer options need to be set to ignore null values, otherwise the
// response will contain null values for the properties that are not set.
// The .NET SignalR client will not be able to parse the response if the null values are present.
// For more information, see https://github.com/dotnet/aspnetcore/issues/60935.
return Results.Json(negotiateResponse, new JsonSerializerOptions(JsonSerializerDefaults.Web)
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
});
});
app.Run();
The preceding code configures the Azure SignalR Service using the ServiceManagerBuilder
class, but doesn't call AddSignalR
or MapHub
. These two extensions aren't required with Serverless mode. The connection string is read from the configuration key ConnectionStrings:signalr
. When using the emulator, only the HTTP endpoint is available. Within the app, you can use the ServiceManager
instance to create a ServiceHubContext
. The ServiceHubContext
is used to broadcast messages and manage connections to clients.
The /negotiate
endpoint is required to establish a connection between the connecting client and the Azure SignalR Service. The ServiceHubContext
is created using the ServiceManager.CreateHubContextAsync
method, which takes the hub name as a parameter. The NegotiateAsync
method is called to negotiate the connection with the Azure SignalR Service, which returns an access token and the URL for the client to connect to.
For more information, see Use Azure SignalR Management SDK.
See also
.NET Aspire