In my previous tutorial, we implemented to save Geolocation (latitude, longitude) in Geography data type column in Sql Server. Now, we will get the nearest N places from the current geo-location of user.
Environment: VS2012,.NET Framework 4.5, ASP.NET Empty Website template, C#, SQL Server v11.0, Entity Framework 5.0 Database First approach.
HTML Structure:
Add a new Web Form and reference jQuery in head tag
<script src="http://ajax.aspnetcdn.com/ajax/jquery/jquery-1.9.0.js"></script>
Add following code
<form id="form1" runat="server">
<p id="message"></p>
<asp:HiddenField ID="hdnLocation" runat="server" />
<asp:Button ID="btnSubmit" runat="server" Text="Get 5 Nearest Places" OnClick="btnSubmit_Click" />
<asp:GridView ID="GridView1" runat="server" CellPadding="3"></asp:GridView>
<div id="map" style="width: 600px; height: 400px;"></div>
</form>
Hidden field is used to save current user geographical position similar to previous post. On submit, Gridview and Map will display the nearest 5 places.
To Get Current User Geo-Location:
We use same HTML5 Geo-Location API to get current user geographical position.
$('[id*=btnSubmit]').prop('disabled', true);
var currentLatLng;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition, showError);
}
else { $("#message").html("Geolocation is not supported by this browser."); }
function showPosition(position) {
currentLatLng = position.coords;
var latlon = "Latitude" + currentLatLng.latitude + "," + "Longitude" + currentLatLng.longitude;
$("#message").html(latlon);
$("[id*=hdnLocation]").val(currentLatLng.longitude + " " + currentLatLng.latitude);
$('[id*=btnSubmit]').prop('disabled',false);
}
function showError(error) {
if (error.code == 1) {
$("#message").html("User denied the request for Geolocation.");
}
else if (error.code == 2) {
$("#message").html("Location information is unavailable.");
}
else if (error.code == 3) {
$("#message").html("The request to get user location timed out.");
}
else {
$("#message").html("An unknown error occurred.");
}
}
By default, submit button is disabled. It is enabled on getting current user geo-location.
Getting The Nearest Places:
First, I would recommend to read my previous post to get idea about database structure. I am using same scene here. The following code is to get the nearest 5 places:
var currentLocation = DbGeography.FromText("POINT(" + hdnLocation.Value + ")");
string[] latlng = hdnLocation.Value.Split(new char[]{' '});
using ( var context = new SampleDBEntities()){
var places = (from u in context.PlaceInfoes
orderby u.Geolocation.Distance(currentLocation)
select u).Take(5).Select(x => new { Name = x.Name, Address = x.Address, City = x.City, State = x.State, Latitude = x.Geolocation.Latitude, Longitude = x.Geolocation.Longitude });
Entity Framework 5 and above supports spatial type operations. Here we are doing order by distance from current location and take top 5 records in LINQ. EF5+ makes it very easy.
To Display Data In GridView:
//Bind GridView
GridView1.DataSource = places.ToList();
GridView1.DataBind();
To Display Data In Map:
We serialize and assign marker points in javascript variable points from server side and on client side, this variable will be used to display markers
//Set points for map
JavaScriptSerializer serializer = new JavaScriptSerializer();
var output = serializer.Serialize(places);
ClientScript.RegisterClientScriptBlock(GetType(), "points", "var points = " + output + ";var currentLoc = { 'Latitude' : " + latlng[1] + ", 'Longitude':"+latlng[0] +" }", true);
}
In above code, currentLoc variable is used to hold current geo-location of user.
on client side:
var map2, infoWindow;
if (typeof points !== "undefined") {
var mapOptions = {
center: new google.maps.LatLng(points[0].Latitude, points[0].Longitude),
zoom: 9,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
infoWindow = new google.maps.InfoWindow();
map2 = new google.maps.Map(document.getElementById("map"), mapOptions);
//marker for current location
var marker = new google.maps.Marker({
position: new google.maps.LatLng(currentLoc.Latitude, currentLoc.Longitude),
map: map2,
icon: 'https://maps.google.com/mapfiles/kml/shapes/schools_maps.png'
});
//marker for nearest places
for (i = 0; i < points.length; i++) {
var data = points[i]
var myLatlng = new google.maps.LatLng(data.Latitude, data.Longitude);
var marker2 = new google.maps.Marker({
position: myLatlng,
map: map2,
title: data.Name
});
(function (marker2, data) {
google.maps.event.addListener(marker2, "click", function (e) {
infoWindow.setContent(data.Name);
infoWindow.open(map2, marker2);
});
})(marker2, data);
}
}
In above javascript code, current location is defined with different marker icon.
Output:
Conclusion:
We saw the application of Sql server Geography data type and good support of Entity framework which makes few lines of code to get the nearest N places done.
Enjoy EF !!