Bound by Design

Shading ZIP Code Boundaries with Virtual Earth and ASP.NET AJAX





Bound by Design

Shading ZIP Code Boundaries with Virtual Earth and ASP.NET AJAX


By Matt Berseth


This article illustrates building a Web application using Microsoft s ASP.NET and Virtual Earth platforms. It starts by walking through creating a simple HTML Web page that uses the Virtual Earth map control to display a map of North America. As the article progresses, this sample is extended to add custom shapes to the map, and eventually develops into an ASP.NET Web application that dynamically plots ZIP code boundaries on the map surface.

To display the map on a Web page, version 5 of the Virtual Earth Map Control SDK is used. This control defines all the classes, methods, and events used to load and interact with the map. Microsoft has an interactive online SDK at that displays the different ways the map control can be manipulated, along with corresponding code samples and API documentation. The table in Figure 1 contains the map control classes this article references.


Virtual Earth JavaScript Members



Provides Virtual Earth map functionality to a Web page. The VEMap constructor requires the ID of the HTML control that will contain the map.


Contains the latitude and longitude of a single point on the globe. The class defines two properties: Latitude and Longitude.


An enumeration of the available VEShapes: Pushpin, Polyline, and Polygon.


Contains information about map shape. A VEShape is a pushpin, a polyline, or a polygon. A pushpin is a single point on the map, a polyline is a line connecting a sequence of points, and a polygon is a set of points that define an enclosed region on the map.


Specifies the color and transparency to use when drawing VEShape objects on the map. The VEColor class defines properties for the red, green, blue, and alpha (transparency) components of the color.

Figure 1: Virtual Earth map control classes.


Initializing and Viewing a Virtual Earth Map

At the very minimum, a page using the Virtual Earth map control is required to include the following three items:

  • An HTML script reference to the JavaScript map control. For version 5, this should refer to
  • An HTML element to contain the map image. The size and position of the map are determined by the style properties of the container element. If height or width is omitted, they ll automatically default to 600 pixels and 400 pixels, respectively.
  • Script code that handles initializing and loading the map. The map is initialized by creating a new VEMap object, passing it the ID of the HTML container element. After the object is created, calling the LoadMap method will load the map image onto the page


Equipped with this information, a sample HTML page can be created by defining these elements. You can copy-paste or manually key-in the following markup and code into a text file, save it with the html extension, and view it in your browser to see how the control behaves when rendered:











The standard map navigation capabilities, like repositioning the map by dragging the mouse and using the trackball to change the maps zoom, are already built-in to the map control. The control also contains a dashboard that allows users to control map navigation, as well as toggle between the road, aerial, and hybrid map views. Figure 2 shows the sample page in Internet Explorer 7.0.


Figure 2: Virtual Earth map of North America.


Adding Shapes to the Map

Now that we ve seen what is required to add Virtual Earth map to a Web page, the map control API is given a closer look. Specifically, we concentrate on the map control s VEShape class and update the sample to use this class to add custom shapes to the map. The VEShape class makes it easy to create and add pushpin, polyline, and polygon shapes to the map. To create a VEShape object, the type of shape (pushpin, polyline, or polygon) is specified using the VEShapeType enumeration, along with the array of VELatLong objects that define the shape. The value of the VEShapeType parameter determines what the VEShape constructor requires for the VELatLong parameter. If the shape is a pushpin, a single VELatLong is required (if an array of VELatLongs is provided, only the first element is used to define the pushpin s location; the other elements are ignored); if the shape is a polyline, an array with two or more VELatLongs are required otherwise, if the shape is a polygon, an array with three or more VELatLongs must be provided.


The pushpin VEShape is useful for identifying a single point on the map. This shape type is commonly used to plot a point on the map, like a restaurant, hotel, or some other place of interest that can be defined by a single latitude and longitude pair. The following JavaScript snippet creates a new pushpin VEShape object and adds it to the map:


// load the map

map = new VEMap('myMap');


var whiteHouse = new VELatLong(38.897540, -77.036444);

// put a pushpin on the white house

var vePushpin = new VEShape(VEShapeType.Pushpin, whiteHouse);



A polyline is a line that connects two or more points on the map. It is created by providing the VEShape constructor the list of VELatLongs that define the points the line should pass through. If more than two points are provided, the line will be drawn through the points in the order they are provided. A common use for a polyline is to display a path between points on the map:


// load the map

map = new VEMap('myMap');


// define some interesting locations

var whiteHouse = new VELatLong(38.897540, -77.036444);

var lincolnMemorial = new VELatLong(38.889370, -77.050123);

var pentagon = new VELatLong(38.870820, -77.056046);

// draw a line from the white house, to the

// lincoln memorial, to the pentagon

var vePolyline =

   new VEShape(VEShapeType.Polyline, [whiteHouse, lincolnMemorial, pentagon]);



A polygon is a circuit or closed path polyline. A polygon is useful for enclosing a region of the map; examples might be the border of a state, area code, or ZIP code:


// load the map

map = new VEMap('myMap');


// define some interesting locations

var whiteHouse = new VELatLong(38.897540, -77.036444);

var lincolnMemorial = new VELatLong(38.889370, -77.050123);

var pentagon = new VELatLong(38.870820, -77.056046);

// draw a polygon, using the

// whitehouse, lincoln memorial and the

// pentagon as the points

var vePolygon =

   new VEShape(VEShapeType.Polygon, [whiteHouse, lincolnMemorial, pentagon]);



A nice feature of the VEShape class is that it provides a common interface to the methods that are used to change the appearance of shape regardless of the shape type. Customization options include giving the shape a title and description, changing the shape s fill color (polygons only), line color (polyline and polygons only), and associating a custom icon with the shape. The table in Figure 3 shows a handful of methods defined by the VEShape class and a short description of each.





Hides and shows the shapes icon. This is ignored for pushpin shapes.


Gets and sets the shapes description.


Gets and sets the shape s title.


Gets and sets the shape s line color (only used for polylines and polygons).


Gets and sets the shape s line width (only used for polylines and polygons).


Gets and sets the shape s fill color (only used for polygons).

Figure 3: VEShape methods.


Dynamically Adding ZIP Codes to the Map

Now that we ve covered the basics, we can extend the example further to dynamically draw a ZIP code on the map s surface. The running sample will be updated to allow users to select a ZIP code from a list. After a selection is made, script on the page will call an ASP.NET Web service to fetch the ZIP code s boundary and dynamically add a polygon to the map that represents the ZIP code. ASP.NET AJAX will be used to invoke the Web service from client script (you can learn more about using ASP.NET AJAX to invoke ASP.NET Web services at After the Web service returns the requested points, the page creates a polygon VEShape object. Finally, this new VEShape object is added to the map in a similar manner as shown previously.


The ZipCodeService ASP.NET Web service is created next. This Web service contains a single Web method: FindZipCodeInfo. FindZipCodeInfo accepts a five-digit US ZIP code as a parameter and returns a string containing the collection of latitude and longitude pairs that define the ZIP code boundary. For this sample, the FindZipCodeInfo Web service will only support retrieving the boundary for the following ZIP codes: 58103, 58104, 32224, and 32246. For simplicity, our service has the latitude and longitudes hard-coded for these four ZIP codes; in a real application, this would be replaced by looking up the ZIP code boundary from a database.


When creating the Web service, we want to make sure it can be easily invoked by our client script. To accomplish this, the System.Web.Script.Services.ScriptServiceAttribute is added to the ZipCodeService s class declaration and the asp:ScriptManager ASP.NET AJAX control is added to our ASP.NET page. The markup for the control includes a child asp:ServiceReference element that references the path to our Web service. Adding the attribute and markup provides ASP.NET AJAX with enough metadata to auto-generate a JavaScript proxy that will be used by client script to invoke the Web service. The proxy is added to the page as the asp:ScriptManager control is rendered. Here s the markup for the asp:ScriptManager:






Now that the ZipCodeService is created, we turn back to the ASP.NET page and add a dropdown list and an input button (again, we are limiting the user to pick between 58103, 58104, 32224, and 32246). The button s onclick event is wired to call the auto-generated ZipCodeService JavaScript proxy, registering callback function s that will be invoked when the Web service call returns. The SucceededCallback function does the work of extracting the latitude and longitudes from the response, creating a new VEShape object representing the ZIP code, and adding the new VEShape object to the map. Here s the markup and code for the input button:



 SucceededCallback, FailedCallback); return false;" />


The ZipCodeService class referenced in the onclick handler is the Web service proxy generated by ASP.NET AJAX. The proxy executes the FindZipCodeInfo Web method asynchronously. Two JavaScript functions, SucceededCallback and FailedCallback, are registered as callbacks and will be invoked when the Web method finishes executing. If an error occurs while invoking the FindZipCodeInfo method, the FailedCallback function is called; otherwise, the SucceedCallback is invoked.


As mentioned, the latitude and longitude pairs that define the ZIP code boundary are returned from the ZipCodeService as a string. The SucceedCallback function first unpacks the string (the ZIP codes are encoded in the following format: {latitude}, {longitude} , the pairs are pipe delimited) and builds a VELatLong array from the coordinates. Next, a polygon VEShape object is created, passing it the VELatLong array. After the polygon is created, the fill color, line color, and line width of the shape are customized so the region can be seen easily on the map (see Figure 4).


Figure 4: A Virtual Earth map displaying the 58103 ZIP code.


Finally, we remove all shapes from the map, add our new polygon to the map, and position the map so our polygon is visible. Here s the JavaScript function that executes these steps:


// This is the callback function that

// processes the value returned by the Web service.

function SucceededCallback(result)


   var points = result;

   if(points.length > 0)


       var latLongTokens = points.split('|');

       var veLatLongs = new Array(latLongTokens.length);

       // populate the VELatLong array

       for(index = 0; index < latLongTokens.length; index++)


            // format= {0},{1}|

           var latitude =


           var longitude =


           //  build the points array from the string

           veLatLongs[index] =

               new VELatLong(latitude, longitude);


       // create the polygon VEShape

       var polygon = new VEShape(



       // set the line color, width and the fill color

       polygon.SetFillColor(new VEColor(0,0,255,.2));

       polygon.SetLineColor(new VEColor(0,0,255,1));


       //  don't display the shapes icon


       //  clear any existing polygons


       //  add our new polygon


       //  set the view to these points






The Microsoft Virtual Earth map control is a JavaScript control that contains a number of built-in functions and exposes a full featured API that developers can use to programmatically interact with a Virtual Earth map. Pushpins, polylines, and polygons can easily be created, customized, and added to the map surface using the techniques shown in this article.


The files accompanying this article are available for download.


Matt Berseth is a Sr. Software Engineer for a top automotive marketing firm located in Jacksonville, FL. He started his career as a developer at Microsoft and continued it with a large transportation management corporation before moving on to his current position. Matt attended college at North Dakota State University where he earned his Master s degree in Software Engineering. In his free time, Matt enjoys reading, writing, hanging out with his friends and family, and watching whatever is on ESPN. You can visit Matt online at or e-mail him at mailto:[email protected].



Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.