Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Lat Lays Flat - Part 4: An ASP.NET 2.0 Google Maps Control

4.20/5 (10 votes)
29 Apr 2006CPOL4 min read 1   1.8K  
An ASP.NET 2.0 Google Maps control.

(Editor's note: The Google API can and has changed so be warned that the code in this article may need to be modified to account for any changes)

Introduction

This is the fourth article in a three article series examining a custom ASP.NET server control I developed to make using the Google Maps API easier for .NET developers. The focus of this article is to highlight the changes I made while porting the GMap control from ASP.NET 1.1 to ASP.NET 2.0. If you're not familiar with the GMap control, I highly recommend reading Part 1, Part 2, and Part 3 first. This article assumes you are familiar with the Google Maps API. You may see references throughout the article to "my control, my GoogleMaps control, my GMap control, etc.". I did not create the Google Maps API, I merely created a wrapper for ASP.NET using C#, XML, and XSL.

The four things to be covered are:

  • ICallbackEventHandler – Using the new built-in callback features of ASP.NET 2.0.
  • Embedded script files – Put your custom JavaScript right into the assembly.
  • Generics – Create strongly typed collections with one line of code.
  • The new web.config – Some new areas of the configuration file.

This code was developed and tested using Visual Studio 2005 Beta 2. I have not tested nor can I guarantee that that code will work in another version/build of Visual Studio.

ICallbackEventHandler

In the ASP.NET 1.1 version of the GMap control, I had to do a lot of extra work to make client callbacks function properly with ASP.NET pages. With .NET 2.0, Microsoft has made using client callbacks as easy as using regular server-side events.

The code below shows the RaiseCallbackEvent() method. The only difference between this and the older version (RaisePostbackEvent()) is the absence of the CallbackHelper.Write() and CallbackHelper.HandleError() calls. ASP.NET takes care of all of the plumbing and all of the client side JavaScript for us.

C#
public string RaiseCallbackEvent(string eventArgument)
{
  string[] ea = eventArgument.Split('|');
  string[] args = null;
  GPointEventArgs pea = null;
  string evt = ea[0];
  string retVal = String.Empty;
  switch (evt)
  {
    // GMap Click event sends the coordinates of the click as event argument
    case "GMap_Click":
      args = ea[1].Split(',');
      pea = new GPointEventArgs(float.Parse(args[0]), float.Parse(args[1]), this);
      retVal = this.OnClick(pea);
      break;
    // GMarker Click event sends the coordinates of the click as event argument
    case "GMarker_Click":
      args = ea[1].Split(',');
      GPoint gp = new GPoint(float.Parse(args[0]), float.Parse(args[1]));
      GMarker gm = new GMarker(gp, args[2]);
      pea = new GPointEventArgs(gp, gm);
      retVal = this.OnMarkerClick(pea);
      break;
    // GMap Move Start event sends the coordinates of the center of the 
    // map where the move started
    case "GMap_MoveStart":
      args = ea[1].Split(',');
      pea = new GPointEventArgs(float.Parse(args[0]), float.Parse(args[1]));
      retVal = this.OnMoveStart(pea);
      break;
    // GMap Move End event sends the coordinates of the center of the 
    // map where the move ended
    case "GMap_MoveEnd":
      args = ea[1].Split(',');
      pea = new GPointEventArgs(float.Parse(args[0]), float.Parse(args[1]));
      retVal = this.OnMoveEnd(pea);
      break;
    // GMap Zoom event sends the old and new zoom levels
    case "GMap_Zoom":
      args = ea[1].Split(',');
      GMapZoomEventArgs zea = new GMapZoomEventArgs(int.Parse(args[0]),
        int.Parse(args[1]));
      retVal = this.OnZoom(zea);
      break;
    // GMap Client Load event
    case "GMap_ClientLoad":
      retVal = this.OnClientLoad();
      break;
    // GMap Map Type Changed event
    case "GMap_MapTypeChanged":
      retVal = this.OnMapTypeChanged();
      break;
    // Default: we don't know what the client was trying to do
    default:
      throw new System.Web.HttpException(
        String.Format("Invalid GMap Event Sender: {0} Event: {1}", this.ID, evt));
  }
  return retVal;
}

Embedded Script Files

Another great feature of ASP.NET 2.0 is the ability to embed files into an assembly (JPEGs, GIFs, js files, XSL files, etc.) and reference them in your pages. This magic is courtesy of the new ClientScriptManager. For more details on this process, read "Embedding Resources in ASP.NET 2.0 Assemblies" by Mark Hines. Version 1.1 of the GMap control relied on the developer to place the proper client files (GMapX.js, GMap.xsl, and CallbackObject.js) in a folder of their web application. This folder had to be referenced in the web.config file. Any changes made to the control required updating the control assembly and possibly the three supporting files. As you can see, this could become a maintenance nightmare. With .NET 2.0, these files are now embedded in the assembly directly. No need to manage multiple files, everything is wrapped up nicely in the DLL file.

The code below found in AssemblyInfo.cs tells the framework that the two files GMapX.js and GMap.xsl can be found in the assembly.

C#
[assembly: System.Web.UI.WebResource("WCPierce.Web.GMapX.js", "text/javascript")]
[assembly: System.Web.UI.WebResource("WCPierce.Web.GMap.xsl", "text/xml")]

Obtaining a reference to the files for use in the page's rendered HTML is a simple method call.

C#
ClientScriptManager cs = Page.ClientScript;
cs.RegisterClientScriptInclude(GMap.ScriptName,
  cs.GetWebResourceUrl(this.GetType(), "WCPierce.Web.GMapX.js"));

The resulting output on your page looks something like this:

JavaScript
<script
  src="http://www.codeproject.com/WCPierceWeb/WebResource.axd?d=3ZY3jtwRvU5AI2&t=634837500"
  type="text/javascript"></script>

<Generics>

If you plan on moving to .NET 2.0 and you haven't already, I strongly recommend learning about generics. Check out "Generics Explained" by zubinraj for a good overview on generics. For version 1.1 of the control, I used CodeSmith to generate a strongly-typed ArrayList for overlays, icons, controls, and points. This resulted in thousands of lines of code for five classes. But that is the price you had to pay for a truly strongly-typed ArrayList. Using generics, the code for GOverlays is now seven (7) lines instead of 2,662.

C#
using System;

namespace WCPierce.Web.UI.WebControls
{
    [Serializable]
    public class GOverlays : System.Collections.Generic.List<GOverlay> { }
}

Pretty amazing 'eh? Seven lines of code and I have a perfectly formed, strongly-typed ArrayList waiting to do my bidding.

The New Web.Config

There are a lot of new features in Configuration for ASP.NET 2.0. For a complete look at the new features, check out "Managing Your ASP.NET Application". The main usage in GMap 2.0 is registering a custom control once in the web.config file and being able to use it throughout your application with full Intellisense. The blurb below shows a portion of the web.config file included in the code download.

XML
<pages>
  <controls>
    <!-- Register our custom controls -->
    <add namespace="WCPierce.Web.UI.WebControls"
      assembly="WCPierce.Web" tagPrefix="wcp"/>
    . . .
  </controls>
</pages>

With this line added you can easily add a GMap control to any page in your application like the code below. You also get full HTML Intellisense for free.

HTML
<wcp:GMap runat="server" id="gMap" Width="750px" Height="525px" />

Conclusion

This article was so short I'm almost embarrassed to call it an article. I wanted to keep it brief, and focus on the changes made to make the GMap take advantage of ASP.NET 2.0. If you want full details on the creation of the GMap control, check out Part 3 where I cover the code in depth. Until next time, Happy Mapping!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)