New to Telerik UI for WinUI? Download free 30-day trial

Routing Using Azure Maps Services

To achieve routing functionality using the Azure Maps services, you can use the custom provider for the Azure Maps services from here and extend it. You can also use the geocoding functionality from here. You can use it to create a URL request for the Microsoft's routing and geocoding APIs and use the response to display the route on the RadMap control. In order to receive valid responses from the routing and geocoding APIs, you will need to pass a valid location and subscription key to the request URL string.

Extending the CustomAzureMapProvider to search routes

public class CustomAzureMapProvider : TiledProvider, ICloneable 
{ 
    private static HttpClient httpClient = new HttpClient(); 
 
    /// <summary>  
    /// Initializes a new instance of the MyMapProvider class.  
    /// </summary>  
    public CustomAzureMapProvider() 
            : base() 
    { 
        CustomAzureMapSource source = new CustomAzureMapSource(); 
        this.MapSources.Add(source.UniqueId, source); 
        this.SetMapSource(source.UniqueId); 
    } 
 
    /// <summary>  
    /// Returns the SpatialReference for the map provider.  
    /// </summary>  
    public override ISpatialReference SpatialReference 
    { 
        get 
        { 
            return new MercatorProjection(); 
        } 
    } 
 
    public static async Task<RouteInfo> GetRouteDirections(string startAddress, string endAddress) 
    { 
        var start = await GetLocation(startAddress); 
        var end = await GetLocation(endAddress); 
 
        return await GetRouteDirections(start, end); 
    } 
 
    private static async Task<RouteInfo> GetRouteDirections(Location start, Location end) 
    { 
        var requestUrl = $"https://atlas.microsoft.com/route/directions/json?api-version=1.0&amp;query={start}:{end}&amp;instructionsType=text&amp;subscription-key={MapHelper.AzureKey}"; 
 
        var response = await httpClient.GetAsync(requestUrl); 
        response.EnsureSuccessStatusCode(); 
 
        var jsonContent = await response.Content.ReadAsStringAsync(); 
        var options = new JsonSerializerOptions 
        { 
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 
            PropertyNameCaseInsensitive = true 
        }; 
 
        var routeData = JsonSerializer.Deserialize<RouteResponse>(jsonContent, options); 
 
        var firstLeg = routeData.Routes[0].Legs[0]; 
        var routeInfo = new RouteInfo() { Points = firstLeg.Points.Select(p => new Location(p.Latitude, p.Longitude)).ToList() }; 
 
        return routeInfo; 
    } 
 
    public async static Task<Location> GetLocation(string address) 
    { 
        var requestUrl = $"https://atlas.microsoft.com/geocode?api-version=2025-01-01&amp;query={address}&amp;subscription-key={MapHelper.AzureKey}"; 
 
        var response = await httpClient.GetAsync(requestUrl); 
        response.EnsureSuccessStatusCode(); 
 
        var jsonContent = await response.Content.ReadAsStringAsync(); 
        var options = new JsonSerializerOptions 
        { 
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase, 
            PropertyNameCaseInsensitive = true 
        }; 
 
        var featureCollection = JsonSerializer.Deserialize<FeatureCollection>(jsonContent, options); 
 
        var firstCoordinates = featureCollection.Features.First().Geometry.Coordinates; 
        var location = new Location(firstCoordinates[1], firstCoordinates[0]); 
 
        return location; 
    } 
 
    public object Clone() 
    { 
        var newProvider = new CustomAzureMapProvider(); 
 
        return newProvider; 
    } 
} 
 
public class FeatureCollection 
{ 
    public List<Feature> Features { get; set; } 
} 
 
public class Feature 
{ 
    public Geometry Geometry { get; set; } 
} 
 
public class Geometry 
{ 
    public List<double> Coordinates { get; set; } 
} 
 
public class RouteInfo 
{ 
    public List<Location> Points { get; set; } 
} 
 
public class RouteResponse 
{ 
    public List<Route> Routes { get; set; } 
} 
 
public class Route 
{ 
    public List<RouteLeg> Legs { get; set; } 
} 
 
public class RouteLeg 
{ 
    public List<RoutePoint> Points { get; set; } 
} 
 
public class RoutePoint 
{ 
    public double Latitude { get; set; } 
    public double Longitude { get; set; } 
} 
Additionally, you can follow the next example, which showcases how to utilize the CustomAzureMapProvider class and and its logic.

Defining the RadMap and the UI elements for the routing logic

<Grid> 
    <Grid.RowDefinitions> 
        <RowDefinition Height="Auto"/> 
        <RowDefinition Height=""/> 
    </Grid.RowDefinitions> 
 
    <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="Auto"/> 
        <ColumnDefinition Width=""/> 
    </Grid.ColumnDefinitions> 
    <StackPanel Orientation="Horizontal" Grid.ColumnSpan="2" Margin="0 0 0 15"> 
        <TextBlock Text="From" FontWeight="SemiBold" VerticalAlignment="Center"/> 
        <TextBox x:Name="SourceTextBox" 
             Text="Sofia" 
             Width="210" 
             Margin="10 0 0 0"/> 
        <TextBlock Text="To" FontWeight="SemiBold" VerticalAlignment="Center" Margin="10 0 0 0"/> 
        <TextBox x:Name="DestinationTextBox" 
             Text="Varna"  
             Width="210" 
             Margin="10 0 0 0"/> 
        <buttons:RadButton Content="Calculate" 
            Width="100" 
            Margin="15 0 0 0" 
            Click="RadButton_Click"/> 
    </StackPanel> 
    <telerik:RadMap x:Name="radMap" Grid.Row="1" Grid.Column="1" MinZoomLevel="3" Margin="15 0 0 0"> 
        <telerik:RadMap.Provider> 
            <local:CustomAzureMapProvider/> 
        </telerik:RadMap.Provider> 
        <telerikMap:VisualizationLayer x:Name="RouteLayer"/> 
    </telerik:RadMap> 
</Grid> 

Using the routing logic of the CustomAzureMapProvider

private async void RadButton_Click(object sender, RoutedEventArgs e) { this.FindRoute(); }

private async void FindRoute() { this.RouteLayer.Items.Clear();

var start = this.SourceTextBox.Text; 
var end = this.DestinationTextBox.Text; 
 
RouteInfo routeInfo = null; 
try 
{ 
    routeInfo = await CustomAzureMapProvider.GetRouteDirections(start, end); 
} 
catch (Exception ex) 
{ 
    throw new Exception("Error getting route directions: " + ex.Message); 
 
    return; 
} 
 
if (routeInfo != null) 
{ 
    PolylineData routeLine = this.CreateNewPolyline(routeInfo.Points, Colors.Red, 3); 
 
    this.RouteLayer.Items.Clear(); 
    this.RouteLayer.Items.Add(routeInfo.Points[0]); 
    this.RouteLayer.Items.Add(routeInfo.Points[routeInfo.Points.Count - 1]); 
 
    this.RouteLayer.Items.Add(routeLine); 
} 
 
var bestView = this.RouteLayer.GetBestView(this.RouteLayer.Items as IEnumerable<object>); 
this.radMap.SetView(bestView); 

}

private PolylineData CreateNewPolyline(IEnumerable directionPoints, Color color, double thickness) { PolylineData routeLine = new PolylineData() { ShapeFill = new MapShapeFill() { Stroke = new SolidColorBrush(color), StrokeThickness = thickness }, Points = new LocationCollection(), };

foreach (var point in directionPoints) 
{ 
    routeLine.Points.Add(point); 
} 
 
return routeLine; 

}

RadMap with a custom provider for the Azure Maps services and routing functionality

RadMap with a custom provider for the Azure Maps services and routing functionality

In this article
Not finding the help you need?