Invoking server side code using AJAX and .ashx handlers for Virtual Earth (Part 2)

Author: Derek Chan

Overview

In part 1 of this series, you learned how to combine client side with server side logic for Virtual Earth purposes.  You will apply this technique using the Mappoint Web Service to execute proximity searching on the server side and plotting the results on a client side Virtual Earth map.

MWSVE.JPG

Figure 1 - MWS / VE integration

What is the Mappoint Web Service?

The Mappoint Web Service (MWS) is Microsoft’s older mapping product that relies on SOAP based communication to transfer data between networks.  In comparsion, VE is much more dynamic than MWS which uses static maps.  However the following features that are available through MWS have not yet implemented into Virtual Earth version 6:

  • Proximity searching
  • Reverse geocoding
  • Datasource querying and management
  • Map imagery localization
  • Traffic incident data

Any of these features can easily be applied to a Virtual Earth application with the use of AJAX and .ashx handlers.

Requirements

This article assumes that you have read some basic knowledge of Web Services and how to invoke MWS FindServiceSoap related calls.  Refer to the following links to help familiar yourself with MWS:

Developing the Mappoint Web Service

http://msdn2.microsoft.com/en-us/library/aa492594.aspx

Getting started with the Mappoint Web Service SDK

http://msdn2.microsoft.com/en-us/library/aa492550.aspx

Make sure you have a copy of the MWS 4.5 SDK at:

http://www.microsoft.com/Downloads/details.aspx?familyid=CB5148A9-F09E-4EC8-992F-16478C0B5D9A&displaylang=en

You’ll also need a VE Developer account with MWS Staging access.  You can apply here if you don’t already have one.

Getting started

You will implement the ‘hello world’ source code used in the previous article with the FindNearby sample provided in the MWS 4.5 SDK (Located at C:\Program Files\Microsoft MapPoint Web Service SDK, Version 4.5\Samples\.NET 2.0\CoreFunctionality\FindNearby\cs after installing) and integrate a proximity search into a VE map.  The FindNearby SDK sample uses the MWS FindServiceSoap.FindNearby method to search for nearby coffee shops using the “FourthCoffeeShop” datasource. 

Start by copying over AJAX.js, Handler.ashx and Handler.ashx.cs to the SDK folder.  Also download the Coffeeshopicon.gif (see screenshot) on the Customer Service Site or copy the same image bundled into the sample source code.

untitled.JPG

Figure 2 - Stock icons used by the Mappoint Web Service

Remember to provide your MWS account information to the web.config


<add key="MPUser" value="Your VE Developer account ID"/>
<add key="MPPass" value="Your VE Developer account password"/>

Listing 1 – Setting your MWS Credentials

Modifying FindNearby.aspx

Include references to AJAX.js as well as the V6 map control and also create a <div> container for the map on the FindNearby.aspx page.  You can also remove the invokeASHX method and fire it when an HTML button is clicked.


 <script type="text/javascript" src="/Portals/0/AJAX.js"></script>      
      <script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6"></script>
      <script type="text/javascript">
      var map = null;
            
      function GetMap()
      {
         map = new VEMap('myMap');
         map.LoadMap();
      }   
...
<input id="buttonFindVE" type="button" value="Find Nearby (VE)" onclick="InvokeASHX();" />
<div id='myMap' style="position:relative; width:500px; height:500px;"></div>

Listing 2 – Modifying the FindNearby.aspx page

Creating the AJAX Request

Next, transfer all your search parameters from the client side to the server side using the XMLHttpRequest object and some DOM manipulation.


function InvokeASHX()
{
    var dataSource = document.getElementById('listDataSource').options[document.getElementById('listDataSource').selectedIndex].value;
    var streetAddress = document.getElementById('textAddressLine').value;
    var primaryCity = document.getElementById('textPrimaryCity').value;
    var secondaryCity = document.getElementById('textSecondaryCity').value;
    var subdivision = document.getElementById('textSubdivision').value;
    var postalCode = document.getElementById('textPostalCode').value;
    var countryRegion = document.getElementById('listCountryRegion').options[document.getElementById('listCountryRegion').selectedIndex].value;
    var radius = document.getElementById('listRadius').options[document.getElementById('listRadius').selectedIndex].value;
    InitXmlHttp();
    xmlhttp.onreadystatechange= XMLHttpRequestCompleted;
    xmlhttp.open("GET", "" + "Handler.ashx"+ "?dataSource="+ dataSource +"&streetAddress="+streetAddress +
    "&primaryCity=" + primaryCity + "&secondaryCity="+ secondaryCity + "&subdivision=" + subdivision +
    "&postalCode=" + postalCode + "&countryRegion="+postalCode + "&radius="+radius , true );
    xmlhttp.send(null);
}

Listing 3 – Retrieving and sending search parameters

Using an .ashx handler to process the request

The context.Request.Params.Get method is an easy way to retrieve data from your querystring.  The proximity searching logic from the FindNearby.aspx.cs file can be copied over to the Handler.ashx.cs with a few slight modifications to get the parameters from the AJAX request rather than directly off the front end.


Address myAddress = new Address();
myAddress.AddressLine = context.Request.Params.Get("streetAddress");
myAddress.PrimaryCity = context.Request.Params.Get("primaryCity");
myAddress.SecondaryCity = context.Request.Params.Get("secondaryCity");
myAddress.Subdivision = context.Request.Params.Get("subdivision");
myAddress.PostalCode = context.Request.Params.Get("postalCode");
myAddress.CountryRegion = context.Request.Params.Get("countryRegion");

Listing 4 – Processing the AJAX request

When processing the results returned from MWS, the latitude/longitude values are be obtained from the FindResult’s FoundLocation object.  The location’s description is a property of the FindResult’s FoundLocation.Entity.Properties array.  You can point to the stock icon using the VEShape.SetCustomIcon method.  For demonstrative purposes, you can use a StringBuilder instance to collect all your JavaScript code.  The StringBuilder instance will be sent back to to the AJAX request and eval’ed at the client side:


myFindNearbyResults = FindService.FindNearby(findNearbySpec);
StringBuilder response = new StringBuilder();
for (int i = 0; i < myFindNearbyResults.Results.Length - 1; i++)
{
response.AppendFormat("var shape = new VEShape(VEShapeType.Pushpin, new VELatLong({0},{1}));",
    myFindNearbyResults.Results[i].FoundLocation.LatLong.Latitude, 
    myFindNearbyResults.Results[i].FoundLocation.LatLong.Longitude);
response.AppendFormat("shape.SetTitle(\'{0}\');",myFindNearbyResults.Results[i].FoundLocation.Entity.Properties[0].Value);
response.Append("shape.SetCustomIcon(\'images/CoffeeShopIcon.gif\');");
response.Append("map.AddShape(shape);");
}

Listing 5 – Formatting the results from a FindNearby call

Finally, set the camera and zoom level.  You can arbitrarily use one of the points in your results and an any zoom level.


response.AppendFormat("map.SetCenterAndZoom(new VELatLong({0},{1}),12);", myFindNearbyResults.Results[0].FoundLocation.LatLong.Latitude,
                    myFindNearbyResults.Results[0].FoundLocation.LatLong.Longitude);
                    
                    

As discussed in the last article, context.Response.Write(string) is sufficient to send information back to the AJAX request:


context.Response.Write(response.ToString());

Now you should have a result similar to the screenshot below.

Figure 3 – FindNearby Fourth Coffee sample modified

It’s interesting to note how similar the Mappoint Web Service and Virtual Earth maps match up.  In the future, you may wish to extend to code above to execute other kinds of logic such as querying through the MWS TrafficIncidents datasource or reverse geocoding user defined points from a VE map.

Conclusion

To recap, the following steps are necessary to integrate MWS into a VE map:

  1. Gather user defined parameters into the JavaScript file
  2. Make an AJAX call to the .ashx handler using XMLHttpRequest object
  3. Setup MWS credentials and gather parameters inside .ashx handler
  4. Process MWS query and send response (JavaScript, JSON, XML, etc..) back to the AJAX request
  5. Use JavaScript eval method to process the response from the server

The source code has been included in this article and can be found at the bottom of this page.  To begin debugging simply add your credentials and build the project.

Article contributed by Derek Chan (www.infusion.com).  Have you got something to contribute?

Code Download
Copyright 2008. Sponsored by Aptovita   |  Terms Of Use  |  Privacy Statement
Content on this site is generated from the developer community and shared freely for your enjoyment and benifit. This site is run independantly of Microsoft and does not express Microsoft's views in any way.