How to draw a marker on OpenStreetMap

openstreetmap leafletjs

To Use OpenStreetMap and draw marker we can use a javascript library, there’s a lot out there but for this example well use leafletjs.com. It’s open source, mobile friendly and lightweight and has a complete features most developers need.

Leafletjs

Now head over to the website and follow the quick start tutorial, that should be enough to get started. After you follow the tutorial, you can create a simple web application with ASP.NET Core with MVC template (follow this tutorial). Add a new controller, name it MapController then create Index.cshtml view for it. Inside the View, include the leafletjs css style and its script inside the head section of the page to initialize the map and don’t forget to put a div element with a certain id inside the body element. This div element is where you want your map would be.
The web application would have a feature like this: everytime a user enter a text inside the search box and click on a search button, we will search the database for the airport’s name. By calling on the MapController Search action via HttpGet Ajax Request. Once the result came out with the result of Airport[], the app will add marker(s) and put the result on the map. So the user can see the airports data on the map by putting a marker at its location.


@{
ViewData["Title"] = "Map";
}
<h2>@ViewData["Title"]</h2>
@section HeadScripts{
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.3/dist/leaflet.css"
integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ=="
crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet.js"
integrity="sha512-tAGcCfR4Sc5ZP5ZoVz0quoZDYX5aCtEm/eu1KhSLj2c9eFrylXZknQYmxUssFaVJKvvc0dJQixhGjG2yXWiV9Q=="
crossorigin=""></script>
<style type="text/css">
#peta{
height: 500px;
width: auto;
margin: 0 auto;
border: 0.2em solid #c75c41;
box-shadow: #55322a;
}
</style>
}
<div class="form-group col-md-4">
<label>Airport Name:</label>
<input type="text" id="airportName" class="form-control" />
<input type="button" id="btnsubmit" value="Search" class="btn btn-default"/>
</div>
<div id="peta"></div>
@section Scripts{
<script type="text/javascript">
$(document).ready(function(){
var mymap = L.map('peta').locate({setView:true, maxZoom:5});
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a&gt; contributors, ' +
'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a&gt;, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a&gt;',
id: 'mapbox.streets'
}).addTo(mymap);
var markers = [];
var polyLines = [];
function Mapping(data){
for(let idx=0; idx < markers.length; idx++){
markers[idx].removeFrom(mymap);
}
markers = [];
for (let index = 0; index < data.length; index++) {
const element = data[index];
console.log(element);
var marker = L.marker([element.latitude, element.longitude], { title: element.name +"" +element.code}).addTo(mymap);
marker.bindPopup(element.name +"("+element.code+")").openPopup();
markers.push(marker);
polyLines.push([element.latitude, element.longitude]);
if(index===0){
mymap.center = [element.latitude, element.longitude];
}
}
}
$('#btnsubmit').click(function(e){
var airportname= $('#airportName').val();
$.ajax({
url:'/map/search?name='+airportname,
method:'GET',
success: function(d){
console.log(d);
Mapping(d);
},
error: function(msg){
console.log(msg);
}
});
});
});
</script>
}

Airport Data

Since this application will fetch a Geolocation data in a form of Latitude and Longitude, for that we’ll create a table with Columns: Airport Name, Latitude, Longitude, Country and City. Create the Table called AIRPORTS and insert the data from openflights.org (download). The additional information like Country and City is for clarity only, we dont want to only show the airports name and its location because it would be confusing for the user. A country and a city where the airport is located will add more information for the user. We’ll build simple map, with a textbox for searching an airport by its name.
This sql command is for creating the Table :

Create table AIRPORTS(ID INT PRIMARY KEY IDENTITY(1,1), Name varchar(350) not null,Code varchar(10), Latitude varchar(50) not null, Longitude varchar(50) not null,City varchar(50) not null, Country varchar(50) not null);

openflights airports data
openflights airports data

Dapper

To access the data from database, we’ll use a simple object mapper for .NET called Dapper. Using this library we don’t need to manage the SqlConnection, we can execute a query and map the results into a strongly typed list. Or execute a command (insert, update, delete), a stored procedure with a sweeping fast query time. This is one of my favorite nuget package, and I use it regularly on many different projects.

ASP.Net Core

The web application itself has no authentication, let it open so anyone can access it. To make things easier on the data access, create a Repository class and called it AirportRepository. Using Dapper we only need to declare a private member for the SqlConnection and a constant string for the ConnectionString. The repository only have one method for searching the airport data by its name.


using System.Collections.Generic;
using System.Data.SqlClient;
using Dapper;
namespace tracking.Models
{
public class AirportRepository{
// change the user id and password accordingly.
private const string connstring = "Data Source=.\\sqlexpress;Initial Catalog=OSM_DB;user id=[id]; password=[password]";
private SqlConnection Connection;
public AirportRepository()
{
this.Connection = new SqlConnection(connstring);
}
public IEnumerable<Airport> Search(string name){
name = "%"+name+"%";
var data = Connection.Query<Airport>(@"select top 100 Name,Code,Latitude,Longitude,City,Country from airports
where name like @name", new {name});
if(data!=null)
{
return data;
}
return null;
}
}
}

Don’t forget to add a private member of AirportRepository inside MapController and add a Constructor with one parameter which took a Repository instance. This is dependency injection via Constructor, it’s a common pattern that developers often uses its also a built in feature that comes with asp.net core by design. In order for the Constructor to get an instance of the Repository, we have to register the Repository as dependency on Startup.cs, you can read more about dependency injection in asp.net core here.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using tracking.Models;
namespace tracking
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddScoped<GPSLocRepository>();
services.AddScoped<AirportRepository>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
//app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}

view raw

osm_startup.cs

hosted with ❤ by GitHub

That’s it, a short introduction for using Openstreetmap and leafletjs in you web application as an alternative of googlemaps. You can download the source code here.

Published by Gadael Sedubun

Developer

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: