Introduction
It is "cloud" Web application to display GPS tracks on Google or Bing maps, based on the latest Windows Azure Software Development Kit (November 2009). This code may be useful to you if you want to start a new Windows Azure application or want to find code to display GPS data with server code on a Google/Bing map. It is not a complete application such as professionally designed sites like Every Trail. The application uses ASP.NET providers that work with Azure Table Storage (AspProviders sample from Windows Azure Code Samples), so it is not so much different from a traditional Web application. It uses Table Storage to store data. SQL Azure was not available when I started developing. I would highly recommend SQL Azure because Table Storage has several limitations (although it is supposed to be faster).
Application Description
I started the application as a clone of the PersonalWebSite sample. It has the standard functionality of register/login. With the Add Track page, you can add a track by uploading a standard GPX file and giving a name, your country and a description. You can also select if the track will be public. In the Tracks page, you can see all the public tracks and your private ones, or filter by user and country. The View button displays the track in the selected map (Google or Bing). If you login as a registered user, a delete button will appear for your own tracks.
The details button displays the track, its points as dots and some statistics. The "map animation" feature offers you a virtual "journey" of the track. The map centers to successive track points with an adjustable speed. A pause/continue button is offered. Bing Bird's eye view is particularly attractive in this mode. Finally a link to display a full Google/Bing web page of the area is offered.
Using the Code
The code works in the local development fabric provided by the SDK. Table Storage is simulated by a database in the default SQL express installation. If you want to publish it in the Windows Azure environment, replace the key values in the ServiceConfiguration.cscfg configuration file.
Table Storage is used for storing track/coordinate data. See the Windows Azure Platform Training Kit for tutorials about Table Storage. You simply derive your entity classes from the base TableServiceEntity
class and query with LINQ code. Unfortunately, Count
and Take
operations are not supported. Paging can be implemented with custom headers, as shown below. For more information, see the video here.
private void DataBindTracks()
{
try
{
DataServiceQuery<trackrow /> tracksQuery = this.GetTracks(this.PageSize);
var continuation = Request["ct"];
if (continuation != null)
{
string[] tokens = continuation.Split('/');
string partitionToken = tokens[0];
string rowToken = tokens[1];
tracksQuery.AddQueryOption("NextPartitionKey", partitionToken).
AddQueryOption("NextRowKey", rowToken);
}
QueryOperationResponse res = (QueryOperationResponse)tracksQuery.Execute();
string nextPartition = null;
string nextRow = null;
res.Headers.TryGetValue("x-ms-continuation-NextPartitionKey", out nextPartition);
res.Headers.TryGetValue("x-ms-continuation-NextRowKey", out nextRow);
dtlTracks.DataKeyField = "TrackId";
dtlTracks.DataSource = res;
dtlTracks.DataBind();
if (nextPartition != null && nextRow != null)
{
navNext.NavigateUrl = string.Format("?ct={0}/{1}", nextPartition, nextRow);
}
else
{
navNext.Enabled = false;
}
if (continuation == null)
{ navPrev.Enabled = false; }
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
throw ex;
}
}
public static DataServiceQuery<trackrow> GetPublicTracks(string country)
{
try
{
GpsDataContext svc = GetGpsDataContext();
DataServiceQuery<trackrow> rows = (DataServiceQuery<trackrow>)
from tr in svc.Tracks where tr.IsPublic == true select tr;
if (!string.IsNullOrEmpty(country))
{ rows = (DataServiceQuery<trackrow>)rows.Where
(tr => tr.Country == country); }
return rows;
}
catch (Exception ex)
{
Log.Write(EventKind.Error, "Could not get tracks" + ex.Message);
throw ex;
}
}
The Back button simply calls the history.go(-1)
JavaScript code to return to the previous page.
Here I have to make a confession. Paging does not work in my application although the continuation headers are returned and used. It always shows the first page. If anyone finds out why, please leave a comment in the article.
The display of the Google map is done server side, using a user control named Google Maps for ASP.NET published at CodeProject in two articles: Part 1 and Part 2. It is a very clever code that optimizes performance by emitting only the coordinate differences of maps between postbacks to the client. It was modified to run in a web application.
For the Bing maps, I used the Virtual Earth server control of the Windows Live SDK. It is not provided anymore by Microsoft but it still works! Additionally, the IPToCountry code, also from CodeProject, is used to find the country of the anonymous visitor.
As far as the rest of the code is concerned, it has no solid architecture, just quick and dirty implementation! Track coordinates are stored in the users' session and the IMapDisplay
interface is used to remove repetitive if(google) else ... decisions. GoogleMapDisplay
and VEMapDisplay
provide the actual map display functionality. Some classes like Panoramio
and ExtJsJsonHelper
are not actually used, they belong to never implemented features!
History
- 20th December, 2009: Initial and most probably final version of the application!
I hope you will find some parts of it useful.