2/14/2022 Admin

Creating Azure Maps Applications In Blazor


image

You can create Microsoft Azure Maps applications in Microsoft Blazor.

In addition to displaying maps, Azure Maps provides a full range of services including; Search, Traffic, Routing, Elevation, Spatial operations, Geolocation, Weather Service and more.

image

See: https://samples.azuremaps.com/ to view live examples what Azure Maps is capable of.

Setting Up Azure Maps

image

Log into your Azure account at https://portal.azure.com/ and select Create a resource.

image

Search for Azure Maps and click Create.

image

Fill in the Forms and click Create.

image

After the Azure Maps account is created you can navigate to it.

image

Copy the Client ID because you will need it in later steps.

Authentication

image

If you click on the Authentication tab, you will note that there are two methods of authenticating to call the Azure Maps API.

However, the Shared Key Authentication is not recommended by Microsoft for use in Web applications. Microsoft only recommends using them only for Daemon apps (see: https://docs.microsoft.com/en-us/azure/azure-maps/how-to-manage-authentication#choose-an-authentication-and-authorization-scenario).

Instead, we will be using AAD (Azure Active Directory) Authentication described here: https://docs.microsoft.com/en-us/azure/azure-maps/how-to-secure-webapp-users.

image

Go to App Registrations.

image

Create a New registration.

image

Give it a name and click the Register button.

image

Save the Client ID and Tenant ID because you will need them in a later step.

Click Certificates & secrets to create an App Key.

image

Click New client secret.

image

Give it a name and an expiration date and click Add to create the secret.

image

Click the button next to the value and save it, you will need it in a later step.

image

Click API permissions then Add a permission.

image

Select APIs my organization uses, search for Azure Maps and select it.

image

Check the box next to Access Azure Maps, and click Add permissions.

image

Finally, click the Grant admin consent button.

image

Return to the Azure Maps account created earlier.

image

Select IAM, Role assignments, then Add Role assignment.

image

Search for Azure Maps, then select the Azure Maps Data Reader role, and click Next.

image

Click Select members.

image

Search for the name of the Azure App Registration, created earlier, and select it.

image

Click Select.

image

Click Review + assign, then on the next screen, click Review + assign again.

Create The Blazor Application

image

Open Visual Studio

image

Select Create a new Project.

image

Select Blazor Server App and click Next.

image

Name it AzureMaps and click Next.

image

Select .Net 6.

Click Create.

image

The project will be created.

image

Right-click on the Project node and select Manage NuGet Packages…

image

Install the following NuGet packages:

image

To support the AzureMapsControl.Components, open the _Layout.cshtml page, and add the following lines to the <head> section:

								
									<
									link
									rel="stylesheet"
									href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.css"
									type="text/css"
									/>
								
									<
									link
									rel="stylesheet"
									href="https://atlas.microsoft.com/sdk/javascript/drawing/0.1/atlas-drawing.min.css"
									type="text/css"
									/>
								
									<
									link
									rel="stylesheet"
									href="https://atlas.microsoft.com/sdk/javascript/indoor/0.1/atlas-indoor.min.css"
									type="text/css"
									/>
								
									<
									style
									>
								
									#map {
								
									position: absolute;
								
									width: 80%;
								
									height: 80%;
								
									}
								
									</
									style
									>
								

Add the following lines to the end of the <body> section (before the </body> tag):

								
									<
									script
									src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/2/atlas.min.js"
									>
									</
									script
									>
								
									<
									script
									src="https://atlas.microsoft.com/sdk/javascript/drawing/0.1/atlas-drawing.min.js"
									>
									</
									script
									>
								
									<
									script
									src="https://atlas.microsoft.com/sdk/javascript/indoor/0.1/atlas-indoor.js"
									>
									</
									script
									>
								
									<
									script
									src="_content/AzureMapsControl.Components/azure-maps-control.js"
									>
									</
									script
									>
								
									<
									script
									type="text/javascript"
									>
								
									azureMapsControl.Extensions.getTokenCallback = (resolve, reject, map) => {
								

								
									DotNet.invokeMethodAsync('AzureMaps', 'GetAccessToken')
								
									.then(function (response) {
								
									return response;
								
									}).then(function (token) {
								
									resolve(token);
								
									});
								
									};
								
									</
									script
									>
								

Note: See full directions at this link: https://github.com/arnaudleclerc/AzureMapsControl.Components

Display Your Current Location

image

As a first step, we will display our current location (then later have the map show us that location).

Open the Program.cs file and add the following code (before the var app = builder.Build(); line):

								
builder.Services
								
									.AddScoped<Darnton.Blazor.DeviceInterop.Geolocation.IGeolocationService,
								
									Darnton.Blazor.DeviceInterop.Geolocation.GeolocationService>();

image

Open the Index.razor page and change all the code to the following:

								
@page "/"
								
@using AzureMapsControl.Components.Map
								
@using Microsoft.Identity.Client
								
@using Darnton.Blazor.DeviceInterop.Geolocation;
								
@inject IJSRuntime JS
								
@inject IConfiguration _configuration
								
@inject IGeolocationService GeolocationService
								

								
									<
									p
									>CurrentLatitude: @CurrentLatitude</
									p
									>
								
									<
									p
									>CurrentLongitude: @CurrentLongitude</
									p
									>
								

							
								
									@code {
								
									protected
									GeolocationResult? CurrentPositionResult {
									get;
									set; }
								

								
									protected
									string
									CurrentLatitude =>
								
									CurrentPositionResult?.Position?.Coords?.Latitude.ToString("F2");
								

								
									protected
									string
									CurrentLongitude =>
								
									CurrentPositionResult?.Position?.Coords?.Longitude.ToString("F2");
								

								
									protected
									override
									async Task OnAfterRenderAsync(bool
									firstRender)
								
									{
								
									if
									(firstRender)
								
									{
								
									CurrentPositionResult = await GeolocationService.GetCurrentPosition();
								
									StateHasChanged();
								
									}
								
									}
								
}

image

In Visual Studio, hit F5 to run the project.

The web browser will open and a popup will show asking for permission to get your current location.

Click Allow.

image

The coordinates of your current location will show.

Show The Map

image

To implement AAD Authentication, the first step is to put the required values in the appsettings.json file (replacing the highlighted yellow parts with your own values):

								
{
								
									"AzureMaps": {
								
									"ClientId": "
										{{ Client ID From Azure Maps Account }}
									",
								
									"AadTenant": "
										{{ Azure Tenant ID }}
									",
								
									"AadAppId": "
										{{ Client ID From Azure App Registration }}
									",
								
									"AppKey": "
										{{ AppKey (secret) From Azure App Registration }}
									"
								
									},
								
									"Logging": {
								
									"LogLevel": {
								
									"Default": "Information",
								
									"Microsoft": "Warning",
								
									"Microsoft.Hosting.Lifetime": "Information",
								
									"AzureMapsControl.Components": "Debug"
								
									}
								
									},
								
									"AllowedHosts": "*"
								
}

image

We then create a AuthService.cs static class (that will be called by the azureMapsControl.Extensions.getTokenCallback method in the _Layout.cshtml file) using the following code:

								
									using
									Microsoft.Identity.Client;
								
									using
									Microsoft.JSInterop;
								

								
									namespace
									AzureMaps.Service
								
{
								
									public
									static
									class
									AuthService
								
									{
								
									private
									const
									string
									AuthorityFormat = "https://login.microsoftonline.com/{0}/oauth2/v2.0";
								
									private
									const
									string
									MSGraphScope = "https://atlas.microsoft.com/.default";
								
									static
									string
									objTenantID;
								
									static
									string
									objAadAppId;
								
									static
									string
									objAppKey;
								

								
									internal
									static
									void
									SetAuthSettings(IConfigurationSection AzureMaps)
								
									{
								
									objTenantID = AzureMaps.GetValue<string>("AadTenant");
								
									objAadAppId = AzureMaps.GetValue<string>("AadAppId");
								
									objAppKey = AzureMaps.GetValue<string>("AppKey");
								
									}
								

								
									[JSInvokable]
								
									public
									static
									async Task<string> GetAccessToken()
								
									{
								
									IConfidentialClientApplication daemonClient;
								

								
									daemonClient = ConfidentialClientApplicationBuilder.Create(objAadAppId)
								
									.WithAuthority(string.Format(AuthorityFormat, objTenantID))
								
									.WithClientSecret(objAppKey)
								
									.Build();
								

								
									AuthenticationResult authResult =
								
									await daemonClient.AcquireTokenForClient(new[] { MSGraphScope }).ExecuteAsync();
								

								
									return
									authResult.AccessToken;
								
									}
								
									}
								
}

image

Next we add the following using statements to the top of Program.cs:

								
									using
									AzureMaps.Data;
								
									using
									AzureMaps.Service;
								
									using
									AzureMapsControl.Components;

Then the following code to get the ClientId from the appsettings.json file, and pass it to the AzureMapsControl service that will be used to display the map:

								
var AzureMaps = builder.Configuration.GetSection("AzureMaps");
								

								
									//This code uses an anonymous authentication
								
builder.Services.AddAzureMapsControl(
								
									configuration => configuration.ClientId = AzureMaps.GetValue<string>("ClientId"));

Finally we add the following code that will initialize the static AuthService class with the settings from the appsettings.json file:

								
AuthService.SetAuthSettings(AzureMaps);

image

Note: This uses a technique to get the values from the appsettings.json file into a static class that can be called by Blazor JavaScript from the article: Calling static .NET methods (in Blazor) , from: https://blazor-university.com .

image

Lastly, we replace all the HTML Markup in the Index.razor file with the following:

								
									<
									AzureMap
									Id="map"
								
									CameraOptions="new CameraOptions { Zoom = 10 }"
								
									StyleOptions="new StyleOptions { ShowLogo = false }"
								
									EventActivationFlags="MapEventActivationFlags.None().Enable(MapEventType.Ready)"
								
									TrafficOptions="new AzureMapsControl.Components.Traffic.TrafficOptions {
									
								
									Incidents = false,
								
									Flow = AzureMapsControl.Components.Traffic.TrafficFlow.Relative }"
								
									OnReady="OnMapReadyAsync"
									/>
								

Also, we replace the OnAfterRenderAsync method with the following:

								
									public
									async Task
									OnMapReadyAsync(MapEventArgs eventArgs)
								
									{
								
									CurrentPositionResult = await GeolocationService.GetCurrentPosition();
								

								
									if
									(CurrentPositionResult.IsSuccess)
								
									{
								
									await eventArgs.Map.SetCameraOptionsAsync(
								
									options => options.Center =
								
									new
									AzureMapsControl.Components.Atlas.Position
								
									(Convert.ToDouble(CurrentLongitude), Convert.ToDouble(CurrentLatitude)));
								

								
									await eventArgs.Map.SetTrafficOptionsAsync(options => options.Incidents =
									true);
								
									}
								
									}
								

image

When we run the application, the map, showing traffic, will show for our current location.

Download

The project is available on the Downloads page on this site.

You must have Visual Studio 2022 (or higher) installed to run the code.

Links

An error has occurred. This application may no longer respond until reloaded. Reload 🗙