Integrating MapPoint Web Service with Virtual Earth 6

Author: Richard Brundritt


In this article we will look at how to use Ajax to access the MapPoint Web Service and display the results on a Virtual Earth Map. This article will primarily focus on accessing data from custom data sources using the FindNearBy, FindByProperty, FindByID, and FindNearRoute MapPoint Web Service methods.


Getting Started


In order to make our application work, we will need to develop three related components:



  • A "back end" class that can extract traffic information form MapPoint

  • A "middle tier" ASP.NET HttpHandler that will act as an AJAX portal connecting our MapPoint class and our VE map.

  • A "front end" Virtual Earth map that will request MapPoint data and display it.




Figure 1 Process of integrating MapPoint into Virtual Earth


Client Side Virtual Earth Map (default.aspx)


The client side page consists of some basic HTML and a set of JavaScript methods to make the appropriate calls to the back end.


The HTML


Our page will consist of a Virtual Earth Map and a button for each MapPoint method we want to call.



<body onload="OnPageLoad('myMap')">
<form id="form1" runat="server">
<div id="myMap" style="position:relative;width:650px;height:400px;"></div>
<input id="getTraffic" type="button" value="Get MWS Traffic" onclick="GetTraffic();"/>
<input id="findNearBy" type="button" value="FindNearBy" onclick="FindNearBy();"/>
<input id="Button1" type="button" value="FindByProperty" onclick="FindByProperty();"/>
<input id="Button2" type="button" value="FindNearRoute" onclick="FindNearRoute();"/>
<input id="Button3" type="button" value="FindByID" onclick="FindByID();"/>
</form>
</body>


Listing 1 The body of default.aspx


The JavaScript (Part 1) – The Map


We need to add a reference to the Virtual Earth Map Control:



<script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6"></script>


Listing 2 Virtual Earth 6 Map Control


We also need an OnPageLoad method to draw our map. At the same time we will define some global variables that we will be using later:



<script>
var map;
var datasource = "MapPoint.FourthCoffeeSample";
var entityName = "FourthCoffeeShops";
var searchRadius = 250;

function OnPageLoad(element)
{
map = new VEMap(element);
map.LoadMap();
}
</script>


Listing 3 Drawing the Map


Loading the default.aspx into a web browser should result in the following:




Figure 2 default.aspx


JavaScript (Part 2) – The AJAX


We will need the following in order for our integration to work:


· A set of methods for making an HTTP request and receiving the result.


· An AddPushpin method so that our page can add pushpins.


Making an HTTP Request

If you have worked with Virtual Earth, you may be familiar with the following code for initializing an XML HTTP object.



var xmlhttp=false;
function InitXmlHttp() {
// Attempt to initialize xmlhttp object
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
// Try to use different activex object
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
xmlhttp = false;
}
}
// If not initialized, create XMLHttpRequest object
if (!xmlhttp && typeof XMLHttpRequest!='undefined')
{
xmlhttp = new XMLHttpRequest();
}

// Define function call for when Request obj state has changed
xmlhttp.onreadystatechange=SearchHandler;
}

function SearchHandler()
{
if (xmlhttp.readyState==4)
{
eval(xmlhttp.responseText);
}
}


Listing 4 JavaScript necessary to make an AJAX call


Now we can make an HTTP call by using initializing the xmlhttp object, and then using the open() and send() methods. When the call is returned, it will automatically be processed by SearchHandler().


The AddPin method

Our handler page is going to return a string representing a set of JavaScript calls. Although we could have the handler send back a set of map.AddPushpin() calls, that creates too big of a dependency between our front and back end. Instead, we are going to have our back end call a JavaScript method called AddPin():



function AddPin(lat, lng, title, description)
{
try
{
var shape = new VEShape(VEShapeType.Pushpin,new VELatLong(lat, lng));
shape.SetTitle(title);
shape.SetDescription(description);
map.AddShape(shape);
}
catch (err)
{
alert(err);
}
}


Listing 5 The AddPin callback method


JavaScript (Part 3) – The AJAX Request functions


We will have four functions, one for every MapPoint method we want to integrate with: FindNearBy, FindByProperty, FindByID, and FindNearRoute.


The FindNearBy function

This function takes the center of the map as the location to center the FindNearBy call with. We also pass along the name of the datasource, the entity type name and the search radius.



function FindNearBy()
{
map.DeleteAllShapes();

var ll = map.GetCenter();
InitXmlHttp();
var msg = "MWSFindHandler.ashx?&FT=FindNearBy&Lat="
+ll.Latitude+"&Lng="+ll.Longitude+"&DBS="+datasource
+"&ENTY="+entityName+"&Dis="+searchRadius;

xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}


Listing 6 The FindNearBy function


The FindByProperty function

This function sends the data source name, the entity type name, an expression and a list of parameters.



function FindByProperty()
{
map.DeleteAllShapes();
var expression = "Subdivision = {0}";
var parameters = "NY"
var ll = map.GetCenter();
InitXmlHttp();
var msg = "MWSFindHandler.ashx?&FT=FindByProperty&DBS="+datasource
+"&ENTY="+entityName+"&Exp="+expression+"&PRM="+parameters;
xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}

Listing 7 The FindByProperty function


The FindByID function

This function uses a comma delimitated string to represent the array of entity ID’s that we want the FindById function to find. The datasource name and entity type name are also passed to the handler to be processed.



function FindByID()
{
map.DeleteAllShapes();

var arrayID = "-11777,-11781,-11789";

InitXmlHttp();
var msg = "MWSFindHandler.ashx?&FT=FindByID&DBS="+datasource
+"&ENTY="+entityName+"&ID="+arrayID;
xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}


Listing 8 The FindByID function


The FindNearRoute function

This function uses the new GetDirections method in Virtual Earth 6 to draw the route on the map. The route options are set so that it uses the MWS routing method. In our request to the handler we send the starting and ending coordinates along with MapPoint datasource name the route is being drawn in, the custom datasource the user is using, the entity type name, the route type and the distance from the route to search.



function FindNearRoute()
{
map.DeleteAllShapes();
var startLocation = new VELatLong(47.301036844193135,-122.32933044433595);
var endLocation = new VELatLong(47.441474801849466,-122.24487304687503);
var mappointDatasource = "MapPoint.NA"
var distance = 5;
var routeType = "Quickest";

var options = new VERouteOptions;
options.UseMWS = true;
options.RouteOptimize = VERouteOptimize.MinimizeTime;

var locations = new Array(startLocation,endLocation);

map.GetDirections(locations, options);

InitXmlHttp();

var msg = "MWSFindHandler.ashx?&FT=FindNearRoute&sLat="+
startLocation.Latitude+"&sLng="+startLocation.Longitude+
"&eLat="+endLocation.Latitude+"&eLng="+endLocation.Longitude+
"&mDBS="+mappointDatasource+"&DBS="+datasource+"&ENTY="+
entityName+"&RT="+routeType+"&DIS="+distance;

xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}


Listing 9 The FindNearRoute function


The Middle Tier – MWSFindHandler.aspx


Now that our main page is finished, we need to create the middle tier. Our handler has three functions:



  • Validate the request

  • Determine which method is being called

  • Call the method in the MWSFindGenerator and pass the response back to the original caller.


In order to build the middle tier, we start with a new Generic HTTP Handler named MWSFindHandler:



<%@ WebHandler Language="C#" Class="MWSFindHandler" %>
using System;
using System.Web;
public class MWSFindHandler: IHttpHandler {

public void ProcessRequest (HttpContext context) {
//We add our code here
}

public bool IsReusable {
get {
return false;
}
}
}


Listing 10 The Basic Handler (MWSFindHandler.aspx)


Once we have our basic handler, we need to modify the ProcessRequest method to meet our needs. We need to determine which find method is being called, check the parameters, create our MWSFindGenerator class, get our data, and write it back to the requesting page:



context.Response.ContentType = "text/plain";
MWSFindGenerator fnbg = new MWSFindGenerator();
if (context.Request.QueryString["FT"] != null)
{
if (context.Request.QueryString["FT"].Equals("FindNearBy"))
{
if (context.Request.QueryString["lat"] != null
&& context.Request.QueryString["lng"] != null
&& context.Request.QueryString["dbs"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["dis"] != null)
{

double lat = Double.Parse(context.Request.QueryString["Lat"]);
double lng = Double.Parse(context.Request.QueryString["Lng"]);
double dis = Double.Parse(context.Request.QueryString["Dis"]);

context.Response.Write(fnbg.FindNearBy(lat, lng,
context.Request.QueryString["DBS"],
context.Request.QueryString["ENTY"], dis));
}
}
else if(context.Request.QueryString["FT"].Equals("FindByProperty"))
{
if (context.Request.QueryString["DBS"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["Exp"] != null
&& context.Request.QueryString["PRM"] != null)
{
context.Response.Write(fnbg.FindByProperty(
context.Request.QueryString["DBS"],
context.Request.QueryString["ENTY"],
context.Request.QueryString["Exp"],
context.Request.QueryString["PRM"]));
}
}
else if(context.Request.QueryString["FT"].Equals("FindNearRoute"))
{
if (context.Request.QueryString["sLat"] != null
&& context.Request.QueryString["sLng"] != null
&& context.Request.QueryString["eLat"] != null
&& context.Request.QueryString["eLng"] != null
&& context.Request.QueryString["mDBS"] != null
&& context.Request.QueryString["DBS"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["RT"] != null
&& context.Request.QueryString["Dis"] != null)
{
double slat = Double.Parse(context.Request.QueryString["sLat"]);
double slng = Double.Parse(context.Request.QueryString["sLng"]);
double elat = Double.Parse(context.Request.QueryString["eLat"]);
double elng = Double.Parse(context.Request.QueryString["eLng"]);
double dis = Double.Parse(context.Request.QueryString["Dis"]);

context.Response.Write(fnbg.FindNearRoute(slat,slng,elat,elng,
context.Request.QueryString["mDBS"],
context.Request.QueryString["DBS"],
context.Request.QueryString["ENTY"],
context.Request.QueryString["RT"], dis));
}
}
else if (context.Request.QueryString["FT"].Equals("FindByID"))
{
if (context.Request.QueryString["DBS"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["ID"] != null)
{
string tempString = (
context.Request.QueryString["ID"]).Replace(" ", "");
char[] sep = { ',' };
int[] arrayID = ParseIntValues(tempString.Split(sep));
context.Response.Write(fnbg.FindByID(
context.Request.QueryString["DBS"],
context.Request.QueryString["ENTY"], arrayID));
}
}
}


Listing 11 Add this to ProcessRequest()


Our FindByID function on our JavaScript side sent a comma delimited string to represent an array. A function will be needed to convert this string into an integer array so that it can be sent to the MapPoint Web Service. This is done using the following method:



private int[] ParseIntValues(string[] stringArray)
{
int[] arrayID = new int[stringArray.Length];
for (int i = 0; i < stringArray.Length; i++)
{
arrayID[i] = Int32.Parse(stringArray[i]);
}
return arrayID;
}


Listing 12 Parse Comma Delimited String into Integer Array


The Back End – MWSFindGenerator.cs


Our back end class needs to have a public method for each of the Find methods we want to use (FindNearBy(), FindByProperty(), FindByID(), and FindNearRoute()) which returns a string consisting of a semi-colon separated sequence of calls to AddPin().


In order to make this work, we need to:



  1. Create a web reference to MapPoint Web Service

  2. Create an instance of the MapPoint Find proxy

  3. Create an instance of the MapPoint Route proxy

  4. Issue a call to the appropriate Find method

  5. Parse the results


Create a Reference to MapPoint


The first thing we need is to add a Web Reference to our ASP.NET project. In Visual Studio, choose Website->Add Web Reference… from the menu. In the wizard, enter the MapPoint staging URL: http://staging.mappoint.net/standard-30/mappoint.wsdl. Change the service name to MapPointService, and you should have a screen that looks like this:




Figure 3 Adding the Web Reference


As soon as you click the Add Reference button, you will have access to the MWS proxy classes.


Execute a Find Request


We'll create a separate C# class to perform all of our MapPoint work. We will need six methods:



  • A constructor to instantiate the MapPoint proxy classes

  • A public FindNearBy() method to perform the FindNearBy work

  • A public FindByProperty() method to perform the FindNearBy work

  • A public FindByID() method to perform the FindNearBy work

  • A public FindNearRoute() method to perform the FindNearBy work

  • A private BuildPin() method to help us parse out the results.


The Constructor

Our basic class and constructor looks like this:



using System;
using System.Security.Authentication;
using System.Collections.Generic;
using System.Configuration;
using MapPointService;
using System.Text;

/// <summary>
/// Summary description for FindNearByGenerator
/// </summary>
public class MWSFindGenerator
{
private MapPointService.FindServiceSoap findService = null;
private MapPointService.RouteServiceSoap routeService = null;

//TODO: Change the following values to your username and password
private String MPUser = ConfigurationManager.AppSettings["username"];
private String MPPass = ConfigurationManager.AppSettings["password"];

public MWSFindGenerator()
{
if (findService == null)
{
findService = new MapPointService.FindServiceSoap();
}
findService.Credentials = new System.Net.NetworkCredential(MPUser, MPPass);
findService.PreAuthenticate = true;

if (routeService == null)
{
routeService = new MapPointService.RouteServiceSoap();
}
routeService.Credentials = new System.Net.NetworkCredential(MPUser, MPPass);
routeService.PreAuthenticate = true;
}
}


Listing 13 The MWSFindGenerator Class


We start by declaring some internal constants for our user name and password (change these to your own values). We also need a member variable for our Find and Route Services.


Next, in the constructor, we create an instance of the MapPoint Find Service and Route Service. We also assign our username and password as credentials, and turn on pre-authentication to help speed up repeated requests to the service.


The FindNearBy Method

We received a latitude and a longitude along with a custom datasource name, the entity type name and the search radius. If you are not familiar with MapPoint, in order to do a FindNearBy we need to:



  1. Create a FindNearbySpecification object

  2. Define our datasource

  3. Set the latitude and longitude

  4. Filter the results to only show results with our entity type name.

  5. Execute a FindNearby() call using our specification.

  6. Parse the results.


Our method looks like this:



public String FindNearBy(double latitude, double longitude, string datasource, string entityName, double distance)
{
StringBuilder results = new StringBuilder();
try
{
FindNearbySpecification findNearbySpec = new FindNearbySpecification();
findNearbySpec.DataSourceName = datasource;
findNearbySpec.Distance = distance;
findNearbySpec.LatLong = new MapPointService.LatLong();
findNearbySpec.LatLong.Latitude = latitude;
findNearbySpec.LatLong.Longitude = longitude;
findNearbySpec.Filter = new MapPointService.FindFilter();
findNearbySpec.Filter.EntityTypeName = entityName;

FindResults foundResults = findService.FindNearby(findNearbySpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}


Listing 14 The FindNearBy Method


Running this method in a browser will display the following results:




Figure 4 FindNearBy on a Virtual Earth Map


The FindByProperty Method


We received a custom datasource name, the entity type name, an expression, and parameters. If you are not familiar with MapPoint, in order to do a FindByProperty we need to:



  1. Create a FindByPropertySpecification object

  2. Define our datasource

  3. Filter the results to only show results with our entity type name.

  4. Filter the results to only show results with our expression

  5. Execute a FindByProperty() call using our specification.

  6. Parse the results.


Our method looks like this:



public String FindByProperty(string datasource, string entityName,
string findExpression, string parameters)
{
StringBuilder results = new StringBuilder();
try
{
FindByPropertySpecification findByPropSpec = new FindByPropertySpecification();
findByPropSpec.DataSourceName = datasource;
findByPropSpec.Filter = new MapPointService.FindFilter();
findByPropSpec.Filter.EntityTypeName = entityName;

findByPropSpec.Filter.Expression = new FilterExpression();
findByPropSpec.Filter.Expression.Text = findExpression;
findByPropSpec.Filter.Expression.Parameters = new object[] {parameters};

FindResults foundResults = findService.FindByProperty(findByPropSpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}


Listing 15 The FindByProperty Method


Loading this method in a browser will display the following results:




Figure 5 FindByProperty on a Virtual Earth Map


The FindByID Method


We received a custom datasource name, the entity type name, and an integer array of entity ID’s. If you are not familiar with MapPoint, in order to do a FindByID we need to:



  1. Create a FindByIDSpecification object

  2. Define our datasource

  3. Filter the results to only show results with our entity type name.

  4. Specify our Entity ID’s

  5. Execute a FindByID() call using our specification.

  6. Parse the results.


Our method looks like this:



public String FindByID(string datasource, string entityTypeName, int[] arrayID)
{
StringBuilder results = new StringBuilder();
try
{
FindByIDSpecification findByIDSpec = new FindByIDSpecification();
findByIDSpec.DataSourceName = datasource;
findByIDSpec.Filter = new MapPointService.FindFilter();
findByIDSpec.Filter.EntityTypeName = entityTypeName;
findByIDSpec.EntityIDs = arrayID;

FindResults foundResults = findService.FindByID(findByIDSpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}


Listing 16 The FindByID Method


Loading this method in a browser will display the following results:




Figure 6 FindByID on Virtual Earth Map


The FindNearRoute Method


We received a custom datasource name, the entity type name, the start and end coordinates of our route, the MapPoint datasoure the route is in, the route type, and the distance around the route to search. If you are not familiar with MapPoint, in order to do a FindNearRoute we need to:



  1. Create a route object that is equivalent to our route in Virtual Earth

  2. Create a FindNearRouteSpecification object

  3. Define our datasource

  4. Filter the results to only show results with our entity type name.

  5. Define our search distance

  6. Define our route

  7. Execute a FindNearRoute() call using our specification.

  8. Parse the results.


Our method looks like this:



public String FindNearRoute(double startLat, double startLong, double endLat,
double endLong, string mappointDatasource, string customDatasource,
string entityTypeName, string routeType, double distance)
{
StringBuilder results = new StringBuilder();
try
{
LatLong[] latLongs = new LatLong[2];
latLongs[0] = new LatLong();
latLongs[1] = new LatLong();
latLongs[0].Latitude = startLat;
latLongs[0].Longitude = startLong;
latLongs[1].Latitude = endLat;
latLongs[1].Longitude = endLong;

SegmentPreference segPref = new SegmentPreference();
if(routeType.Equals("Quickest"))
{
segPref = SegmentPreference.Quickest;
}
else if(routeType.Equals("Shortest"))
{
segPref = SegmentPreference.Shortest;
}
else //PreferredRoads
{
segPref = SegmentPreference.PreferredRoads;
}

Route route = routeService.CalculateSimpleRoute(latLongs, mappointDatasource,
segPref);

FindNearRouteSpecification findRouteSpec = new FindNearRouteSpecification();
findRouteSpec.DataSourceName = customDatasource;
findRouteSpec.Filter = new MapPointService.FindFilter();
findRouteSpec.Filter.EntityTypeName = entityTypeName;
findRouteSpec.Distance = distance;
findRouteSpec.Route = route;

FindResults foundResults = findService.FindNearRoute(findRouteSpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}


Listing 17 The FindNearRoute Method


Loading this method in a browser will display the following results:




Figure 7 FindNearRoute on a Virtual Earth Map


The BuildPin Method


Our BuildPin() method processes each of the returned MapPoint result objects and generates a string calling the AddPin() method. The most challenging part of this method is extracting the interesting properties out of the Location object. Unfortunately, the MapPoint Location object's properties array is numerically index. Therefore we convert it to a Dictionary object so that we can pull out values by name.



private String BuildPin(Location result)
{
Dictionary<String, String> props = new Dictionary<String, String>();
foreach (MapPointService.EntityPropertyValue prop in result.Entity.Properties)
{
props.Add(prop.Name, System.Convert.ToString(prop.Value));
}
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("'<table>");
sb.Append("<tr><td>{0}</td></tr>");
sb.Append("<tr><td>{1}, {2}</td></tr>");
sb.Append("<tr><td>{3}</td></tr>");
sb.Append("<tr><td>{4}</td></tr>");
sb.Append("<tr><td>{5}</td></tr>");
sb.Append("</table>'");

Object[] pinParams = new Object[4];
pinParams[0] = result.LatLong.Latitude;
pinParams[1] = result.LatLong.Longitude;
pinParams[2] = String.Format("'{0}'",result.Entity.Name);
pinParams[3] = String.Format(sb.ToString(),
new Object[] {props["AddressLine"], props["PrimaryCity"], props["Subdivision"],
props["CountryRegion"], props["PostalCode"],props["Phone"]});
return String.Format("AddPin({0},{1},{2},{3});", pinParams);
}


Listing 18 The Build Pin Method


Conclusion


Once you have the basic process in place for making AJAX calls, you can easily link to other datasources. You can also easily expand upon these methods to include other MapPoint methods.


This article was written by Richard Brundritt from Infusion Development.


Final Code


The following code should give you everything you need to rebuild this application, provided that you have an MWS account, and that you have created your Web Reference properly.


default.aspx


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="default.aspx.cs" Inherits="_default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>
<head id="Head1" runat="server">
<title>Traffic with VE6 and MWS</title>
<script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6"></script>
<script>
var map;
var datasource = "MapPoint.FourthCoffeeSample";
var entityName = "FourthCoffeeShops";
var searchRadius = 250;

function OnPageLoad(element)
{
map = new VEMap(element);
map.LoadMap();
}

function AddPin(lat, lng, title, description)
{
try
{
var shape = new VEShape(VEShapeType.Pushpin,new VELatLong(lat, lng));
shape.SetTitle(title);
shape.SetDescription(description);
map.AddShape(shape);
}
catch (err)
{
alert(err);
}
}

function FindNearBy()
{
map.DeleteAllShapes();

var ll = map.GetCenter();
InitXmlHttp();
var msg = "MWSFindHandler.ashx?&FT=FindNearBy&Lat="+ll.Latitude+"&Lng="+ll.Longitude+"&DBS="+datasource+"&ENTY="+entityName+"&Dis="+searchRadius;
xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}

function FindByProperty()
{
map.DeleteAllShapes();
var expression = "Subdivision = {0}";
var parameters = "NY"
var ll = map.GetCenter();
InitXmlHttp();
var msg = "MWSFindHandler.ashx?&FT=FindByProperty&DBS="+datasource+"&ENTY="+entityName+"&Exp="+expression+"&PRM="+parameters;
xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}

function FindNearRoute()
{
map.DeleteAllShapes();
var startLocation = new VELatLong(47.301036844193135,-122.32933044433595);
var endLocation = new VELatLong(47.441474801849466,-122.24487304687503);
var mappointDatasource = "MapPoint.NA"
var distance = 5;
var routeType = "Quickest";

var options = new VERouteOptions;
options.UseMWS = true;
options.RouteOptimize = VERouteOptimize.MinimizeTime;

var locations = new Array(startLocation,endLocation);

map.GetDirections(locations, options);

InitXmlHttp();

var msg = "MWSFindHandler.ashx?&FT=FindNearRoute&sLat="+
startLocation.Latitude+"&sLng="+startLocation.Longitude+
"&eLat="+endLocation.Latitude+"&eLng="+endLocation.Longitude+
"&mDBS="+mappointDatasource+"&DBS="+datasource+"&ENTY="+
entityName+"&RT="+routeType+"&DIS="+distance;

xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}

function FindByID()
{
map.DeleteAllShapes();

var arrayID = "-11777,-11781,-11789";

InitXmlHttp();
var msg = "MWSFindHandler.ashx?&FT=FindByID&DBS="+datasource+"&ENTY="+entityName+"&ID="+arrayID;
xmlhttp.open("GET",msg,true);
xmlhttp.send(null);
}

var xmlhttp=false;
function InitXmlHttp() {
// Attempt to initialize xmlhttp object
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
// Try to use different activex object
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
xmlhttp = false;
}
}
// If not initialized, create XMLHttpRequest object
if (!xmlhttp && typeof XMLHttpRequest!='undefined')
{
xmlhttp = new XMLHttpRequest();
}

// Define function call for when Request obj state has changed
xmlhttp.onreadystatechange=searchHandler;
}

function searchHandler()
{
if (xmlhttp.readyState==4)
{
eval(xmlhttp.responseText);
}
}
</script>
</head>
<body onload="OnPageLoad('myMap')">
<form id="form1" runat="server">
<div id="myMap" style="position:relative;width:650px;height:400px;"></div>
<input id="findNearBy" type="button" value="FindNearBy" onclick="FindNearBy();"/>
<input id="Button1" type="button" value="FindByProperty" onclick="FindByProperty();"/>
<input id="Button2" type="button" value="FindNearRoute" onclick="FindNearRoute();"/>
<input id="Button3" type="button" value="FindByID" onclick="FindByID();"/>
</form>
</body>
</html>


Listing 19 Final code for default.aspx


MWSFindHandler.aspx


<%@ WebHandler Language="C#" Class="MWSFindHandler" %>

using System;
using System.Web;

public class MWSFindHandler : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
MWSFindGenerator fnbg = new MWSFindGenerator();

if (context.Request.QueryString["FT"] != null)
{
if (context.Request.QueryString["FT"].Equals("FindNearBy"))
{
if (context.Request.QueryString["lat"] != null
&& context.Request.QueryString["lng"] != null
&& context.Request.QueryString["dbs"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["dis"] != null)
{

double lat = Double.Parse(context.Request.QueryString["Lat"]);
double lng = Double.Parse(context.Request.QueryString["Lng"]);
double dis = Double.Parse(context.Request.QueryString["Dis"]);

context.Response.Write(fnbg.FindNearBy(lat, lng, context.Request.QueryString["DBS"], context.Request.QueryString["ENTY"], dis));
}
}
else if(context.Request.QueryString["FT"].Equals("FindByProperty"))
{
if (context.Request.QueryString["DBS"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["Exp"] != null
&& context.Request.QueryString["PRM"] != null)
{
context.Response.Write(fnbg.FindByProperty(context.Request.QueryString["DBS"], context.Request.QueryString["ENTY"],context.Request.QueryString["Exp"], context.Request.QueryString["PRM"]));
}
}
else if(context.Request.QueryString["FT"].Equals("FindNearRoute"))
{
if (context.Request.QueryString["sLat"] != null
&& context.Request.QueryString["sLng"] != null
&& context.Request.QueryString["eLat"] != null
&& context.Request.QueryString["eLng"] != null
&& context.Request.QueryString["mDBS"] != null
&& context.Request.QueryString["DBS"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["RT"] != null
&& context.Request.QueryString["Dis"] != null)
{
double slat = Double.Parse(context.Request.QueryString["sLat"]);
double slng = Double.Parse(context.Request.QueryString["sLng"]);
double elat = Double.Parse(context.Request.QueryString["eLat"]);
double elng = Double.Parse(context.Request.QueryString["eLng"]);
double dis = Double.Parse(context.Request.QueryString["Dis"]);

context.Response.Write(fnbg.FindNearRoute(slat,slng,elat,elng,context.Request.QueryString["mDBS"], context.Request.QueryString["DBS"], context.Request.QueryString["ENTY"], context.Request.QueryString["RT"], dis));
}
}
else if (context.Request.QueryString["FT"].Equals("FindByID"))
{
if (context.Request.QueryString["DBS"] != null
&& context.Request.QueryString["enty"] != null
&& context.Request.QueryString["ID"] != null)
{
string tempString = (context.Request.QueryString["ID"]).Replace(" ", "");
char[] sep = { ',' };
int[] arrayID = ParseIntValues(tempString.Split(sep));

context.Response.Write(fnbg.FindByID(context.Request.QueryString["DBS"], context.Request.QueryString["ENTY"], arrayID));
}
}
}
}

private int[] ParseIntValues(string[] stringArray)
{
int[] arrayID = new int[stringArray.Length];

for (int i = 0; i < stringArray.Length; i++)
{
arrayID[i] = Int32.Parse(stringArray[i]);
}

return arrayID;
}

public bool IsReusable
{
get
{
return false;
}
}
}


Listing 20 Final Code for MWSFindHandler.aspx


MWSFindGenerator.cs


using System;
using System.Security.Authentication;
using System.Collections.Generic;
using System.Configuration;
using MapPointService;
using System.Text;

/// <summary>
/// Summary description for FindNearByGenerator
/// </summary>
public class MWSFindGenerator
{
private MapPointService.FindServiceSoap findService = null;
private MapPointService.RouteServiceSoap routeService = null;

//TODO: Change these values to your MWS account information
private String MPUser = "username";
private String MPPass = "password";

public MWSFindGenerator()
{
if (findService == null)
{
findService = new MapPointService.FindServiceSoap();
}
findService.Credentials = new System.Net.NetworkCredential(MPUser, MPPass);
findService.PreAuthenticate = true;

if (routeService == null)
{
routeService = new MapPointService.RouteServiceSoap();
}
routeService.Credentials = new System.Net.NetworkCredential(MPUser, MPPass);
routeService.PreAuthenticate = true;
}

public String FindNearBy(double latitude, double longitude, string datasource, string entityName, double distance)
{
StringBuilder results = new StringBuilder();
try
{
FindNearbySpecification findNearbySpec = new FindNearbySpecification();
findNearbySpec.DataSourceName = datasource;
findNearbySpec.Distance = distance;
findNearbySpec.LatLong = new MapPointService.LatLong();
findNearbySpec.LatLong.Latitude = latitude;
findNearbySpec.LatLong.Longitude = longitude;
findNearbySpec.Filter = new MapPointService.FindFilter();
findNearbySpec.Filter.EntityTypeName = entityName;

FindResults foundResults = findService.FindNearby(findNearbySpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}

public String FindByProperty(string datasource, string entityName, string findExpression, string parameters)
{
StringBuilder results = new StringBuilder();
try
{
FindByPropertySpecification findByPropSpec = new FindByPropertySpecification();
findByPropSpec.DataSourceName = datasource;
findByPropSpec.Filter = new MapPointService.FindFilter();
findByPropSpec.Filter.EntityTypeName = entityName;

findByPropSpec.Filter.Expression = new FilterExpression();
findByPropSpec.Filter.Expression.Text = findExpression;
findByPropSpec.Filter.Expression.Parameters = new object[] {parameters};

FindResults foundResults = findService.FindByProperty(findByPropSpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}

public String FindNearRoute(double startLat, double startLong, double endLat, double endLong, string mappointDatasource, string customDatasource, string entityTypeName, string routeType, double distance)
{
StringBuilder results = new StringBuilder();
try
{
LatLong[] latLongs = new LatLong[2];
latLongs[0] = new LatLong();
latLongs[1] = new LatLong();
latLongs[0].Latitude = startLat;
latLongs[0].Longitude = startLong;
latLongs[1].Latitude = endLat;
latLongs[1].Longitude = endLong;

SegmentPreference segPref = new SegmentPreference();

if(routeType.Equals("Quickest"))
{
segPref = SegmentPreference.Quickest;
}
else if(routeType.Equals("Shortest"))
{
segPref = SegmentPreference.Shortest;
}
else //PreferredRoads
{
segPref = SegmentPreference.PreferredRoads;
}

Route route = routeService.CalculateSimpleRoute(latLongs, mappointDatasource, segPref);

FindNearRouteSpecification findRouteSpec = new FindNearRouteSpecification();
findRouteSpec.DataSourceName = customDatasource;
findRouteSpec.Filter = new MapPointService.FindFilter();
findRouteSpec.Filter.EntityTypeName = entityTypeName;
findRouteSpec.Distance = distance;
findRouteSpec.Route = route;

FindResults foundResults = findService.FindNearRoute(findRouteSpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}

public String FindByID(string datasource, string entityTypeName, int[] arrayID)
{
StringBuilder results = new StringBuilder();
try
{
FindByIDSpecification findByIDSpec = new FindByIDSpecification();
findByIDSpec.DataSourceName = datasource;
findByIDSpec.Filter = new MapPointService.FindFilter();
findByIDSpec.Filter.EntityTypeName = entityTypeName;
findByIDSpec.EntityIDs = arrayID;


FindResults foundResults = findService.FindByID(findByIDSpec);
foreach (FindResult fr in foundResults.Results)
{
results.Append(BuildPin(fr.FoundLocation));
}
}
catch (Exception e)
{
results.Append("Alert('Error: ");
results.Append(e.ToString());
results.Append("');");
}
return results.ToString();
}

private String BuildPin(Location result)
{
Dictionary<String, String> props = new Dictionary<String, String>();
foreach (MapPointService.EntityPropertyValue prop in result.Entity.Properties)
{
props.Add(prop.Name, System.Convert.ToString(prop.Value));
}
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("'<table>");
sb.Append("<tr><td>{0}</td></tr>");
sb.Append("<tr><td>{1}, {2}</td></tr>");
sb.Append("<tr><td>{3}</td></tr>");
sb.Append("<tr><td>{4}</td></tr>");
sb.Append("<tr><td>{5}</td></tr>");
sb.Append("</table>'");

Object[] pinParams = new Object[4];
pinParams[0] = result.LatLong.Latitude;
pinParams[1] = result.LatLong.Longitude;
pinParams[2] = String.Format("'{0}'",result.Entity.Name);
pinParams[3] = String.Format(sb.ToString(),
new Object[] {props["AddressLine"], props["PrimaryCity"], props["Subdivision"], props["CountryRegion"], props["PostalCode"],props["Phone"]});
return String.Format("AddPin({0},{1},{2},{3});", pinParams);
}
}


Listing 21 Final Code for MWSFindGenerator.csw

Copyright 2009. Sponsored by nsquared   |  Terms Of Use  |  Privacy Statement
Content on this site is generated from the developer community and shared freely for your enjoyment and benefit. This site is run independently of Microsoft and does not express Microsoft's views in any way.