You can get the code mentioned in this article from GitHub.
Note
You can get the code mentioned in this article from GitHub.
Important
Raw connection strings appear in this article for demonstration purposes only.
A connection string includes the authorization information required for your application to access Azure SignalR Service. The access key inside the connection string is similar to a root password for your service. In production environments, always protect your access keys. Use Azure Key Vault to manage and rotate your keys securely and secure your connection string using Microsoft Entra ID and authorize access with Microsoft Entra ID.
Avoid distributing access keys to other users, hard-coding them, or saving them anywhere in plain text that is accessible to others. Rotate your keys if you believe they may have been compromised.
Prerequisites
The following prerequisites are needed for this quickstart:
Visual Studio Code, or other code editor. If you don't already have Visual Studio Code installed, download Visual Studio Code here.
An Azure subscription. If you don't have an Azure subscription, create one for free before you begin.
In this section, you create a basic Azure SignalR instance to use for your app. The following steps use the Azure portal to create a new instance, but you can also use the Azure CLI. For more information, see the az signalr create command in the Azure SignalR Service CLI Reference.
In the upper-left side of the page, select + Create a resource.
On the Create a resource page, in the Search services and marketplace text box, enter signalr and then select SignalR Service from the list.
On the SignalR Service page, select Create.
On the Basics tab, you enter the essential information for your new SignalR Service instance. Enter the following values:
Field
Suggested Value
Description
Subscription
Choose your subscription
Select the subscription you want to use to create a new SignalR Service instance.
Resource group
Create a resource group named SignalRTestResources
Select or create a resource group for your SignalR resource. It's useful to create a new resource group for this tutorial instead of using an existing resource group. To free resources after completing the tutorial, delete the resource group.
Deleting a resource group also deletes all of the resources that belong to the group. This action can't be undone. Before you delete a resource group, make certain that it doesn't contain resources you want to keep.
Enter a unique resource name to use for the SignalR resource. If testsignalr is already taken in your region, add a digit or character until the name is unique.
The name must be a string of 1 to 63 characters and contain only numbers, letters, and the hyphen (-) character. The name can't start or end with the hyphen character, and consecutive hyphen characters aren't valid.
Region
Choose your region
Select the appropriate region for your new SignalR Service instance.
Select Change and then choose Free (Dev/Test Only). Choose Select to confirm your choice of pricing tier.
Azure SignalR Service has three pricing tiers: Free, Standard, and Premium. Tutorials use the Free tier, unless noted otherwise in the prerequisites.
For more information about the functionality differences between tiers and pricing, see Azure SignalR Service pricing
Service mode
Choose the appropriate service mode
Use Default when you host the SignalR hub logic in your web apps and use SignalR service as a proxy. Use Serverless when you use Serverless technologies such as Azure Functions to host the SignalR hub logic.
Classic mode is only for backward compatibility and isn't recommended to use.
# Initialize a function project
func init --worker-runtime dotnet
# Add SignalR Service package reference to the project
dotnet add package Microsoft.Azure.WebJobs.Extensions.SignalRService
Bash
# Initialize a function project
func init --worker-runtime dotnet-isolated
# Add extensions package references to the project
dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Http
dotnet add package Microsoft.Azure.Functions.Worker.Extensions.SignalRService
dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Timer
Using your code editor, create a new file with the name Function.cs. Add the following code to Function.cs:
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Newtonsoft.Json;
namespaceCSharp
{
publicstaticclassFunction
{
privatestatic HttpClient httpClient = new HttpClient();
privatestaticstring Etag = string.Empty;
privatestaticstring StarCount = "0";
[FunctionName("index")]
publicstatic IActionResult GetHomePage([HttpTrigger(AuthorizationLevel.Anonymous)]HttpRequest req, ExecutionContext context)
{
var path = Path.Combine(context.FunctionAppDirectory, "content", "index.html");
returnnew ContentResult
{
Content = File.ReadAllText(path),
ContentType = "text/html",
};
}
[FunctionName("negotiate")]
publicstatic SignalRConnectionInfo Negotiate(
[HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req,
[SignalRConnectionInfo(HubName = "serverless")] SignalRConnectionInfo connectionInfo)
{
return connectionInfo;
}
[FunctionName("broadcast")]
publicstaticasync Task Broadcast([TimerTrigger("*/5 * * * * *")] TimerInfo myTimer,
[SignalR(HubName = "serverless")] IAsyncCollector<SignalRMessage> signalRMessages)
{
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/azure/azure-signalr");
request.Headers.UserAgent.ParseAdd("Serverless");
request.Headers.Add("If-None-Match", Etag);
var response = await httpClient.SendAsync(request);
if (response.Headers.Contains("Etag"))
{
Etag = response.Headers.GetValues("Etag").First();
}
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
var result = JsonConvert.DeserializeObject<GitResult>(await response.Content.ReadAsStringAsync());
StarCount = result.StarCount;
}
await signalRMessages.AddAsync(
new SignalRMessage
{
Target = "newMessage",
Arguments = new[] { $"Current star count of https://github.com/Azure/azure-signalr is: {StarCount}" }
});
}
privateclassGitResult
{
[JsonRequired]
[JsonProperty("stargazers_count")]
publicstring StarCount { get; set; }
}
}
}
C#
using System.Net;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
namespacecsharp_isolated;
publicclassFunctions
{
privatestaticreadonly HttpClient HttpClient = new();
privatestaticstring Etag = string.Empty;
privatestaticint StarCount = 0;
[Function("index")]
publicstatic HttpResponseData GetHomePage([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req)
{
var response = req.CreateResponse(HttpStatusCode.OK);
response.WriteString(File.ReadAllText("content/index.html"));
response.Headers.Add("Content-Type", "text/html");
return response;
}
[Function("negotiate")]
publicstatic HttpResponseData Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
[SignalRConnectionInfoInput(HubName = "serverless")] string connectionInfo)
{
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "application/json");
response.WriteString(connectionInfo);
return response;
}
[Function("broadcast")]
[SignalROutput(HubName = "serverless")]
publicstaticasync Task<SignalRMessageAction> Broadcast([TimerTrigger("*/5 * * * * *")] TimerInfo timerInfo)
{
var request = new HttpRequestMessage(HttpMethod.Get, "https://api.github.com/repos/azure/azure-signalr");
request.Headers.UserAgent.ParseAdd("Serverless");
request.Headers.Add("If-None-Match", Etag);
var response = await HttpClient.SendAsync(request);
if (response.Headers.Contains("Etag"))
{
Etag = response.Headers.GetValues("Etag").First();
}
if (response.StatusCode == HttpStatusCode.OK)
{
var result = await response.Content.ReadFromJsonAsync<GitResult>();
if (result != null)
{
StarCount = result.StarCount;
}
}
returnnew SignalRMessageAction("newMessage", newobject[] { $"Current star count of https://github.com/Azure/azure-signalr is: {StarCount}" });
}
privateclassGitResult
{
[JsonPropertyName("stargazers_count")]
publicint StarCount { get; set; }
}
}
The code in Function.cs has three functions:
GetHomePage is used to get a website as client.
Negotiate is used by the client to get an access token.
Broadcast is periodically called to get the star count from GitHub and then broadcast messages to all clients.
The client interface for this sample is a web page. We render the web page using the GetHomePage function by reading HTML content from file content/index.html. Now let's create this index.html under the content subdirectory with the following content:
Azure Functions requires a storage account to work. You can install and run the Azure Storage Emulator. Or you can update the setting to use your real storage account with the following command:
It's almost done now. The last step is to set a connection string of the SignalR Service to Azure Function settings.
Confirm the SignalR Service instance was successfully created by searching for its name in the search box at the top of the portal. Select the instance to open it.
Select Keys to view the connection strings for the SignalR Service instance.
Copy the primary connection string, and then run the following command.
After the Azure function is running locally, open http://localhost:7071/api/index, and you can see the current star count. If you star or unstar in the GitHub, you get a star count refreshing every few seconds.
Clean up resources
If you're not going to continue to use this app, delete all resources created by this quickstart with the following steps so you don't incur any charges:
In the Azure portal, select Resource groups on the far left, and then select the resource group you created. Alternatively, you may use the search box to find the resource group by its name.
In the window that opens, select the resource group, and then click Delete resource group.
In the new window, type the name of the resource group to delete, and then click Delete.
In this quickstart, you built and ran a real-time serverless application locally. Next, learn more about bi-directional communication between clients and Azure Functions with Azure SignalR Service.
Change a JavaScript web app update mechanism from polling to real-time push-based architecture with SignalR Service, Azure Cosmos DB and Azure Functions. Use Vue.js and JavaScript to use SignalR using Visual Studio Code.
Build end-to-end solutions in Microsoft Azure to create Azure Functions, implement and manage web apps, develop solutions utilizing Azure storage, and more.