ASP.NET Cross-Browser, Cross-Device Geolocation in the Browser

Here is a solution that will get you a geolocation for mapping purposes regardless of the browser or device. The DOM Geolocation API is implemented by most modern browsers in the navigator.geolocation object. The problem is, not all devices and browsers implement it the same way. By the use of several scripts and the addition of a server-side fallback method, it is possible to get a valid latitude and longitude for mapping purposes in every case.

Here is the page-level script code to do this:

<script src="http://code.google.com/apis/gears/gears_init.js" type="text/javascript"
        charset="utf-8"></script>
    <script src="Scripts/geo.js?id=1" type="text/javascript" charset="utf-8"></script>  
    <script type="text/javascript" charset="utf-8">

        if (geo_position_js.init()) {
            var map1 = document.getElementById("map1");
                geo_position_js.getCurrentPosition(success_callback, error_callback, { enableHighAccuracy: true });
        }
      

        function success_callback(p) {
            try {
                var lat = document.getElementById("Lat");
                lat.value = p.coords.latitude;
                var lng = document.getElementById("Lng");
               lng.value = p.coords.longitude;
                map1.Longitude = lng.value;
                map1.Latitude = lat.value;
                 __doPostBack(null, null);
            }
            catch (e) { }
        }

        function error_callback(p) {
        }
    </script>

  
   The first script uses Google's gears object (used in Chrome, for example) which stores the browser's geolocation information. The second script is an implementation that looks for different device types and handles the "quirks". The inline third script simply implements all the above and populates two hidden fields with the latitude and longitude. Since I am using the Artem.GoogleMap server control in this case, we have to trigger a postback to get the control to render a map.

   Now what if none of this works? Let's have a look at the ASP.NET page codebehind:

    protected void Page_Load(object sender, EventArgs e)
         {
             if (!String.IsNullOrEmpty(Lat.Value) && !String.IsNullOrEmpty(Lng.Value))
            {
                double latitude = double.Parse(Lat.Value);
                double longitude = double.Parse(Lng.Value);
                var request = new GeoRequest(latitude, longitude);
                var response = request.GetResponse();
                 if (response.Status == GeoStatus.OK)
                {
                    FormattedAdr.Text = response.Results[0].FormattedAddress;
                    map1.Address = FormattedAdr.Text;
                 }
             }

             else
            {
                var loc = GEOIP.GeoLocation.GetLocation();
                map1.Latitude = loc.Latitude;
                map1.Longitude = loc.Longitude;
                FormattedAdr.Text = loc.City + " " + loc.Region + " " + loc.PostalCode;
                map1.DataBind();
            }
        }

You can see above that if the hidden fields are not empty, we issue a GoogleGeocoding request and map the coordinates. And, if that fails, I use the free MaxMind Geolocation javascript API, but I do this server-side as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;

namespace GEOIP
{
   public static class GeoLocation
    {
        
       public static  Location GetLocation()
       {
           try
           {
               WebClient wc = new WebClient();
               string s = wc.DownloadString("http://j.maxmind.com/app/geoip.js");
               wc.Dispose();
               /*  SAMPLE
       function geoip_country_code() { return 'US'; }
               function geoip_country_name() { return 'United States'; }
               function geoip_city()         { return 'Deland'; }
               function geoip_region()       { return 'FL'; }
               function geoip_region_name()  { return 'Florida'; }
               function geoip_latitude()     { return '29.0575'; }
               function geoip_longitude()    { return '-81.3344'; }
               function geoip_postal_code()  { return ''; }
               function geoip_area_code()    { return '386'; }
               function geoip_metro_code()   { return '534'; } */

               s = s.Replace("function geoip_country_code() { return '", "");
               s = s.Replace("function geoip_country_name() { return '", "");
               s = s.Replace("function geoip_city()         { return '", "");
               s = s.Replace("function geoip_region()       { return '", "");
               s = s.Replace("function geoip_region_name()  { return '", "");
               s = s.Replace("function geoip_latitude()     { return '", "");
               s = s.Replace("function geoip_longitude()    { return '", "");
               s = s.Replace("function geoip_postal_code()  { return '", "");
               s = s.Replace("function geoip_area_code()    { return '", "");
               s = s.Replace("function geoip_metro_code()   { return '", "");
               s = s.Replace("'; }", "");
               string[] s2 = s.Split("\n".ToCharArray());


               Location loc = new Location();
               loc.CountryCode = s2[0];
               loc.CountryName = s2[1];
               loc.City = s2[2];
               loc.Region = s2[3];
               loc.RegionName = s2[4];
               loc.Latitude = double.Parse(s2[5]);
               loc.Longitude = double.Parse(s2[6]);
               loc.PostalCode = s2[7];
               loc.AreaCode = s2[8];
               loc.MetroCode = s2[9];
               return loc;
           }
           catch
           {
               return null;
           }
       }
    }
}

public  class Location
    {
         public string CountryCode { get; set; }
         public string CountryName { get; set; }
         public string City { get; set; }
        public string Region { get; set; }
        public string RegionName { get; set; }
         public double Latitude { get; set; }
        public double Longitude { get; set; }
         public string PostalCode { get; set; }
         public string AreaCode { get; set; }
        public string MetroCode { get; set; }
        
    }

The result is that we can get a map for virtually any browser or device. You can download the sample Visual Studio 2010 solution, which includes the two Artem libraries in it's /bin folder. The complete Artem GoogleMaps setup is available on Codeplex.com

By Peter Bromberg   Popularity  (7671 Views)