Introduction
Imagine a logistics team watching a fleet of delivery trucks move across a city map, each driver adding notes that appear instantly on every colleague’s screen. That level of synchronicity is no longer a futuristic concept; it is achievable today with .NET 8, SignalR, and Azure Maps. The combination delivers low‑latency, geospatial collaboration without sacrificing the robustness of C# back‑ends.
Architecture Overview
A typical real‑time collaborative mapping solution consists of three layers. The client layer runs JavaScript or Blazor WebAssembly, rendering Azure Maps tiles and handling user interactions. The server layer is a .NET 8 Web API that hosts a SignalR hub for bidirectional messaging. Finally, Azure Maps provides tile services, geocoding, and route calculations via its REST endpoints. By decoupling the map UI from the messaging core, you gain scalability and can replace any component without a full rewrite.
Setting Up a .NET 8 Project
Start with the .NET 8 SDK (released November 2023). Create a minimal API project, add the SignalR package, and reference the Azure.Maps library. The following commands prepare the environment on a Windows or Linux developer machine.
dotnet new web -n RealTimeMapApp --framework net8.0
cd RealTimeMapApp
dotnet add package Microsoft.AspNetCore.SignalR
dotnet add package Azure.Maps.RoutingAfter the packages are installed, open Program.cs and register the hub.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.SignalR;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSignalR();
var app = builder.Build();
app.MapHub<MapHub>("/mapHub");
app.Run();
public class MapHub : Hub
{
public async Task BroadcastLocation(string userId, double lat, double lng, string note)
{
await Clients.Others.SendAsync("LocationUpdated", new { userId, lat, lng, note });
}
}This hub exposes a single method, BroadcastLocation, which forwards a driver’s position and annotation to every connected client except the sender.
Integrating SignalR for Real‑Time Collaboration
On the front end, use the official SignalR JavaScript client. The connection lifecycle is straightforward: create a HubConnection, start it, then listen for the LocationUpdated event. The following snippet shows how to push a new point when a user clicks the map.
import * as signalR from "@microsoft/signalr";
const connection = new signalR.HubConnectionBuilder()
.withUrl("/mapHub")
.withAutomaticReconnect()
.build();
connection.start().catch(err => console.error(err));
map.on('click', e => {
const payload = { userId: myId, lat: e.position[0], lng: e.position[1], note: "Arrived" };
connection.invoke('BroadcastLocation', payload.userId, payload.lat, payload.lng, payload.note);
});
connection.on('LocationUpdated', data => {
// Render a marker for the other user
map.addMarker({ position: [data.lat, data.lng], title: data.note });
});Because SignalR uses WebSockets when available, latency typically stays under 100 ms for payloads under 1 KB, which is more than sufficient for live map updates.
Using Azure Maps SDK
Azure Maps supplies vector tiles, search, and routing APIs that integrate directly with the client map control. Register an Azure Maps account, copy the primary key, and embed the map in HTML.
<script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"></script>
<div id="myMap" style="width:100%;height:600px"></div>
<script>
const map = new atlas.Map('myMap', {
subscriptionKey: 'YOUR_AZURE_MAPS_KEY',
center: [-122.33, 47.6],
zoom: 12
});
</script>When a driver adds a note, you can enrich it with Azure Maps reverse‑geocode results, turning raw coordinates into human‑readable addresses. The REST call is a simple GET request; the response includes a formattedAddress field you can attach to the marker.
Implementing Collaborative Features
Beyond simple point sharing, many applications need shared drawing, region selection, or live route optimization. Extend the hub with additional methods, for example DrawPolygon that accepts an array of lat‑lng pairs. On the client, broadcast the polygon and render it with atlas.Polygon. Because SignalR serializes objects as JSON, you can pass complex structures without custom serializers.
public async Task DrawPolygon(string userId, double[][] vertices, string label)
{
await Clients.All.SendAsync("PolygonDrawn", new { userId, vertices, label });
}In practice, you might limit the size of vertices to 50 points to keep bandwidth low. Azure Maps supports up to 10 000 vertices per polygon, but most collaborative use‑cases stay well under that threshold.
Performance and Scaling Tips
When the user base grows to hundreds of concurrent drivers, the hub can become a bottleneck. Deploy the API to Azure App Service or Azure Kubernetes Service with at least two instances, and enable the Azure SignalR Service as a backplane. This offloads connection management and guarantees message ordering across instances.
Another practical tip is to batch location updates. Instead of sending a message for every GPS ping (often every second), aggregate points for 2‑3 seconds and send a single payload. This reduces the number of WebSocket frames by up to 70 % while keeping the UI responsive.
Conclusion
Combining .NET 8, SignalR, and Azure Maps gives developers a powerful stack for building real‑time collaborative mapping applications. The minimal API approach keeps the server lightweight, SignalR ensures sub‑second data propagation, and Azure Maps delivers enterprise‑grade geospatial services. By following the code snippets and scaling recommendations above, you can launch a production‑ready solution that lets teams see, edit, and discuss geographic data as it happens.
Sources
Microsoft Docs – ASP.NET Core SignalR
Azure Maps Documentation – Official Microsoft site
Microsoft Learn – .NET 8 Minimal APIs
Author: Mahmut Sarıkaya — sarikayadev.com