Skip to main content
Integrations 8 min read

Integrating HERE Maps API for JavaScript with ASP.NET MVC

asp net hero image

This comprehensive blog post details the step-by-step process of integrating HERE Maps into an ASP.NET MVC project. This how-to guide aims to help developers and customers troubleshoot common issues with HERE Maps integration within the ASP.net environment. It provides:

  • A clear setup guide for ASP.NET MVC projects.
  • Detailed instructions on incorporating HERE Maps JavaScript libraries.
  • Practical examples of implementing and customizing map functionalities
  • Tips for handling interactive map elements and route visualizations.

 

HERE asp .net solution

 

Prerequisites

• Visual Studio installed for Windows or Visual Studio Code installed for Mac.

• If using Mac and terminal make sure to install .NET Core SDK.

• Basic understanding of ASP.NET MVC.

• A HERE platform account to obtain an API key.

 

Step 1: Creating an ASP.NET MVC Project

1. Open Visual Studio and select "Create a new project."

2. Choose the "ASP.NET Core Web Application" template and click "Next."

3. Name your project HereMapsProject and click "Create."

4. Select "Web Application (Model-View-Controller)" and ensure .NET Core and ASP.NET Core are selected. Click "Create."

Or (from Mac Terminal)

1. mkdir HereMapsIntegration

2. cd HereMapsIntegration

3. dotnet new mvc

 

Step 2: Adding Dependencies

Include the HERE Maps API for JavaScript by referencing the necessary files in your project.

 

Step 3: Creating the Layout

The _Layout.cshtml file in ASP.NET MVC defines the common layout for your web pages. Here’s how we set it up:

Copied
        <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
   <title>@ViewData["Title"] - HereMapsProject</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/HereMapsProject.styles.css" asp-append-version="true" />
    <link rel="stylesheet" type="text/css" href="https://js.api.here.com/v3/3.1/mapsjs-ui.css" />
    <script src="https://js.api.here.com/v3/3.1/mapsjs-core.js"></script>
    <script type="text/javascript" src="https://js.api.here.com/v3/3.1/mapsjs-harp.js" charSet="utf-8"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-service.js"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-ui.js"></script>
    <script src="https://js.api.here.com/v3/3.1/mapsjs-mapevents.js"></script>
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container-fluid">
                <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">HereMapsProject</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                       aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>
    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2024 - HereMapsProject - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
   &nbsp;    </div>
    </footer>
    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>
    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>
  

Step 4: Creating the Home View

The Index.cshtml file defines the content for the home page. Here’s how it looks:
 

Copied
        @{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1 class="display-4">Welcome to HERE Maps Integration</h1>
    <p>Explore the map integration below.</p>
</div>

<!-- Map container -->
<div id="jobHereRouteMap" style="width: 100%; height: 500px;"></div>
<!-- Directions panel -->
<div id="here-directions-panel" style="width: 100%;"></div>

@section Scripts {
    <!-- Ensure the paths are correct; they should point to where your scripts are located in the wwwroot/js folder -->
    <script src="~/js/hereMapsIntegration.js"></script>
    <script>
       document.addEventListener("DOMContentLoaded", function() {
            // Configuration object for the DFHereMap function
            var config = {
                mapDivId: 'jobHereRouteMap',
                directionsPanelId: 'here-directions-panel',
                initialLat: 52.53086,&nbsp; // You can adjust these coordinates
                initialLng: 13.38469,
                apiKey: 'yourapikey'&nbsp; // Replace this with your actual HERE API key
            };

            try {
                var hereMap = new DFHereMap(config);
                hereMap.initialize();
            } catch (e) {
                console.error("Error initializing the map:", e);
            }
        });
    </script>
}
  

 

Step 5: Creating the JavaScript Integration

The hereMapsIntegration.js file contains the JavaScript code to integrate HERE Maps. Here’s the complete code:

DFHereMap Function

1. Initialization:

Copied
        var herePlatform = new H.service.Platform({
    'apikey': 'yourapikey'
});
  

This initializes the HERE platform with your API key.

2. Engine and Layers:

Copied
        var engineType = H.Map.EngineType['HARP'];
var defaultLayers = herePlatform.createDefaultLayers({
    engineType: H.Map.EngineType['HARP']
});
  

Configures the map to use the HARP engine and default layers.

3. Map Container:

Copied
        var mapDiv = document.getElementById(configuration.mapDivId);
if (!mapDiv) {
    console.error("Map div not found");
    return;
}
  

Retrieves the HTML element where the map will be rendered.

4. Map Initialization:

Copied
        var map = new H.Map(mapDiv, defaultLayers.vector.normal.map, {
    zoom: 14,
    engineType: H.Map.EngineType['HARP'],
    center: { lat: configuration.initialLat, lng: configuration.initialLng }
});
  

Initializes the map with default settings.

5. Map Events and UI:

Copied
        var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
var ui = H.ui.UI.createDefault(map, defaultLayers);
  

Adds interactivity and default UI controls to the map.

6. Route Instructions Panel:

Copied
        var routeInstructionsContainer = document.getElementById(configuration.directionsPanelId);
  

Retrieves the HTML element where route instructions will be displayed.

7. Waypoint Marker:

Copied
        var waypointMarkers = [];
var routeLine, rerouteLine, currentRoute;

var svgCircle = '<svg width="20" height="20" version="1.1" xmlns="http://www.w3.org/2000/svg">' +
    '<circle cx="10" cy="10" r="7" fill="blue" stroke="blue" stroke-width="4"/>' +
    '</svg>';
var waypointCreateMarker = new H.map.Marker({
    lat: 0,
    lng: 0,
    visibility: false,
    volatility: true
}, {
    icon: new H.map.Icon(svgCircle, {
        anchor: { x: 10, y: 10 }
    })
});
waypointCreateMarker.draggable = true;
map.addObject(waypointCreateMarker);
  

Defines a custom marker for waypoints on the map.

8. Centering the Map:

Copied
        this.setCenter = function(lat, lng) {
    map.setCenter({ lat: lat, lng: lng });
};
  

A method to center the map at specified coordinates.

9. Drawing the Route:

Copied
        this.drawRoute = function(route) {
    if (routeLine) {
        map.removeObject(routeLine);
    }

    var linestrings = [];
    route.sections.forEach((section) => {
       linestrings.push(H.geo.LineString.fromFlexiblePolyline(section.polyline));
    });

    var multiLineString = new H.geo.MultiLineString(linestrings);

    routeLine = new H.map.Polyline(multiLineString, {
        style: { lineWidth: 10, strokeColor: 'rgba(0, 128, 255, 0.7)' }
    });

    map.addObject(routeLine);
    map.getViewModel().setLookAtData({ bounds: routeLine.getBoundingBox() });
    this.addManeuversToPanel(route);
};
  

Draws the calculated route on the map.

10. Adding Maneuvers to the Panel:

Copied
        this.addManeuversToPanel = function(route) {
    var nodeOL = document.createElement('ol');
    nodeOL.style.fontSize = 'small';
    nodeOL.style.marginLeft = '5%';
    nodeOL.style.marginRight = '5%';
    nodeOL.className = 'directions';

    route.sections.forEach((section) => {
        section.actions.forEach((action) => {
            var li = document.createElement('li');
            var spanArrow = document.createElement('span');
            var spanInstruction = document.createElement('span');

     &nbsp;      spanArrow.className = 'arrow ' + (action.direction || '') + action.action;
            spanInstruction.innerHTML = action.instruction;
            li.appendChild(spanArrow);
           li.appendChild(spanInstruction);
            nodeOL.appendChild(li);
        });
    });

    routeInstructionsContainer.innerHTML = '';
   routeInstructionsContainer.appendChild(nodeOL);
};
  

Populates the directions panel with turn-by-turn instructions.

11. Requesting a Route:

Copied
        this.requestRoute = function(origin, destination) {
    var router = herePlatform.getRoutingService(null, 8);
    var routingParameters = {
        routingMode: 'fast',
        transportMode: 'car',
        origin: origin,
        destination: destination,
        return: 'polyline,turnByTurnActions,actions,instructions,travelSummary'
    };

   router.calculateRoute(routingParameters, (result) => {
        this.drawRoute(result.routes[0]);
    }, (error) => {
        console.error('Routing error:', error.message);
    });
}; 
  

Sends a request to the HERE Routing API to calculate a route.

12. Initializing the Map:

Copied
        this.initialize = function() {
    this.requestRoute('52.5160,13.3779', '48.8566,2.3522');
};
  

Initializes the map with a default route.

13. Utility to Remove Route Line:

Copied
        function removeRouteLine() {
    if (routeLine) {
        map.removeObject(routeLine);
        routeLine = null;
    }
}
  

Removes the existing route line from the map.

Complete JavaScript Code

Copied
        function DFHereMap(configuration) {
    var herePlatform = new H.service.Platform({
        'apikey': 'yourapikey'
    });
    var engineType = H.Map.EngineType['HARP'];
    var defaultLayers = herePlatform.createDefaultLayers({
        engineType: H.Map.EngineType['HARP']
    });

    var mapDiv = document.getElementById(configuration.mapDivId);
    if (!mapDiv) {
        console.error("Map div not found");
        return;
    }

    var map = new H.Map(mapDiv, defaultLayers.vector.normal.map, {
        zoom: 14,
        engineType: H.Map.EngineType['HARP'],
        center: { lat: configuration.initialLat, lng: configuration.initialLng }
    });

    var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
    var ui = H.ui.UI.createDefault(map, defaultLayers);

    var routeInstructionsContainer = document.getElementById(configuration.directionsPanelId);
    var waypointMarkers = [];
    var routeLine, rerouteLine, currentRoute;

    var svgCircle = '<svg width="20" height="20" version="1.1" xmlns="http://www.w3.org/2000/svg">' +
        '<circle cx="10" cy="10" r="7" fill="blue" stroke="blue" stroke-width="4"/>' +
        '</svg>';
    var waypointCreateMarker = new H.map.Marker({
        lat: 0,
        lng: 0,
        visibility: false,
        volatility: true
    }, {
        icon: new H.map.Icon(svgCircle, {
            anchor: { x: 10, y: 10 }
        })
    });
    waypointCreateMarker.draggable = true;
    map.addObject(waypointCreateMarker);

    this.setCenter = function(lat, lng) {
        map.setCenter({ lat: lat, lng: lng });
    };

    this.drawRoute = function(route) {
        if (routeLine) {
            map.removeObject(routeLine);
        }

        var linestrings = [];
        route.sections.forEach((section) => {
           linestrings.push(H.geo.LineString.fromFlexiblePolyline(section.polyline));
        });

        var multiLineString = new H.geo.MultiLineString(linestrings);

        routeLine = new H.map.Polyline(multiLineString, {
            style: { lineWidth: 10, strokeColor: 'rgba(0, 128, 255, 0.7)' }
        });

        map.addObject(routeLine);
       map.getViewModel().setLookAtData({ bounds: routeLine.getBoundingBox() });
        this.addManeuversToPanel(route);
    };

    this.addManeuversToPanel = function(route) {
        var nodeOL = document.createElement('ol');
        nodeOL.style.fontSize = 'small';
        nodeOL.style.marginLeft = '5%';
        nodeOL.style.marginRight = '5%';
        nodeOL.className = 'directions';

        route.sections.forEach((section) => {
           section.actions.forEach((action) => {
                var li = document.createElement('li');
                var spanArrow = document.createElement('span');
                var spanInstruction = document.createElement('span');

                spanArrow.className = 'arrow ' + (action.direction || '') + action.action;
                spanInstruction.innerHTML = action.instruction;
               li.appendChild(spanArrow);
               li.appendChild(spanInstruction);
       &nbsp;        nodeOL.appendChild(li);
            });
        });

       routeInstructionsContainer.innerHTML = '';
       routeInstructionsContainer.appendChild(nodeOL);
    };

    this.requestRoute = function(origin, destination) {
        var router = herePlatform.getRoutingService(null, 8);
        var routingParameters = {
            routingMode: 'fast',
            transportMode: 'car',
            origin: origin,
            destination: destination,
            return: 'polyline,turnByTurnActions,actions,instructions,travelSummary'
        };

       router.calculateRoute(routingParameters, (result) => {
           this.drawRoute(result.routes[0]);
        }, (error) => {
            console.error('Routing error:', error.message);
        });
    };

    this.initialize = function() {
       this.requestRoute('52.5160,13.3779', '48.8566,2.3522');
    };

    // Additional utilities and methods as required
    function removeRouteLine() {
        if (routeLine) {
            map.removeObject(routeLine);
            routeLine = null;
        }
    }
}
  

 

Running the Project

1. Place the JavaScript file hereMapsIntegration.js in the wwwroot/js folder of your project.

2. Ensure the paths in _Layout.cshtml is in the Views/Shared folder, and Index.cshtml is in the Views/Home folder inside the root of the project.

3. Run the project by pressing F5 or clicking the run button in Visual Studio in Windows or Visual Studio Code if you are using Mac, you can also run the project by going to the root of the project and type command “dotnet run” from the terminal.

3. The application will run at http://localhost:5139

 

Conclusion

By following this blog, you have successfully integrated HERE Maps into your ASP.NET MVC project. This integration allows you to display maps, calculate routes, and provide turn-by-turn navigation. The detailed explanation of each code snippet ensures you understand how each part of the integration works, empowering you to customize and expand upon this foundation.

Thanks for reading! Drop us a line if you have any feedback or questions below or come by is our Slack workspace

@heredev

Sachin Jonda

Sachin Jonda

Lead Onboarding Engineer

Have your say

Sign up for our newsletter

Why sign up:

  • Latest offers and discounts
  • Tailored content delivered weekly
  • Exclusive events
  • One click to unsubscribe