Parsing Addresses and More with the MapPoint Web Service Find APIs - Implementing MapPoint Lookup AJAX Application (Page 3 of 5 )
The implementation of this application consists of developing the following:
- The web page that hosts JavaScript that makes async calls to the server
- An HTTP Handler that processes async requests and returns proper JavaScript
- JavaScript that makes async calls.
Let’s look at each step in detail.
Developing the web page. In this step, simply create an ASPX page that has the input place textbox with the following event wired up:
<input id="place" onkeyup="DoLookup()" type="text" size="56">
The input textbox"place"has theonkeyupevent wired up to theDoLookup()method, which will be called each time the user types in a character.
Also define adivelement to hold the results; this element acts as a dynamic list box to show results. If no results are found, thedivis hidden as an invisible element on the page, and if search results are found, thedivis visible for the user to select the desired find result:
<div id="placepanel" UNSELECTABLE='on' style="VISIBILITY: hidden;"></div>
The next step is to implement the HTTP Handler that processes find requests on HTTP GET.
Developing the HTTP Handler. To develop an HTTP Handler, you need to implement theSystem.Web.IHttpHandlerinterface, which requires overriding theProcessRequestmethod that handles the incoming request.
You can read more about implementing HTTP Handlers on MSDN at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/ html/frlrfsystemwebihttphandlerclassprocessrequesttopic. asp?frame=true.
In this method, you check an incoming request’s query string to see whether there is any place name; if a place name exists, make aFindServiceSoap.Findmethod call to return matching find results. The results need to be formatted so that the calling JavaScript can understand and display the contents. So, I decided to do the result formatting on the server side in the HTTP handler and simply return the find results that are display-ready. The following code shows theProcessRequestmethod implementation:
public void ProcessRequest(HttpContext context)
{
//See incoming place query string parameter
string input = context.Request["place"] as string;
if(input == null || input == string.Empty)
{
context.Response.Write("var invalidInputFound = 0;");
return;
}
//If there is a valid input call MapPoint Web Service
try
{
//See if this has a cache item:
string response = context.Cache[input] as string;
if(response != null)
{
context.Response.Write("ShowLocation(" + response + ");");
return;
}
else
{
String[] findings = null;
//Call MapPoint Web Service and get the place names into
//the findings string array
. . . .
//Now write back appropriate JavaScript
if(findings == null || findings.Length == 0)
{
context.Response.Write("var novalidOutputFound = 0;");
return;
}
System.Text.StringBuilder sb = new System.Text.StringBuilder();
int count = findings.Length;
sb.Append(""");
for(int i =0; i< count; i++)
{
//Open div and add id
sb.Append("<div id='findresult_" + i.ToString() + "' ");
//Add unselectable = on
sb.Append(" UNSELECTABLE='on' ");
//Add findresult content
sb.Append("<img align=absmiddle src=arrow.gif border=0> " +
findings[i].Trim().Replace("'", "\'"));
//close div
sb.Append("</div>");
}
sb.Append(""");
//Write back the necessary JavaScript and
//add this entry to cache so that we don't have to hit MapPoint
//Web Service
if(sb.Length > 5)
{
//Write JavaScript
context.Response.Write("ShowLocation(" + sb.ToString() + ");");
//Add to cache
context.Cache.Add(input, sb.ToString(), null,
System.DateTime.MaxValue,
TimeSpan.FromHours(6),
System.Web.Caching.CacheItemPriority.Default,
null);
}
else
{
context.Response.Write("var zeroOutputFound = 0;");
}
}
return;
}
catch(Exception ex)
{
context.Response.Write("var errorMesage = '" + ex.Message + "';");
}
}
This HTTP handler writes appropriate JavaScript back to the client as a response to any incoming request. For example, an incoming request such as the following:
http://yourHTTPHandlerUrl?place=New%20York
results in the following JavaScript being sent back as response:
ShowLocation("<div id='findresult_0' UNSELECTABLE='on' ><img align=absmiddle
src=arrow.gif border=0> New York, New York, United States</div><div id='findresult_1'
UNSELECTABLE='on'><img align=absmiddle src=arrow.gif border=0> New York (state),
United States</div><div id='findresult_2' UNSELECTABLE='on'><img align=absmiddle
src=arrow.gif border=0> New York (county), New York, United States</div><div
id='findresult_3' UNSELECTABLE='on'><img align=absmiddle src=arrow.gif border=0> New
York, Santa Rosa, Florida, United States</div><div id='findresult_4'
UNSELECTABLE='on'><img align=absmiddle src=arrow.gif border=0> New York, Wayne, Iowa,
United States</div>");
You can also simply return an array of strings in JavaScript and let the client code do the formatting for the display, but I chose to implement it on the server side since it simplifies the JavaScript implementation.
The next step is to develop the JavaScript to glue these pieces together.
Developing the JavaScript. You might have noticed a couple of JavaScript functions that I have been using so far:
DoLookup
Captures the user’s key inputs and sends an
asynchronous call to the HTTP Handler.
ShowLocation
Displays the find match results to the user in a
dynamic drop-down list.
Let’s see how to implement these two functions.
TheDoLookupfunction uses XMLHTTP functionality to send the request that we developed in the previous step asynchronously to the HTTP handler; a simplified version ofDoLookupis shown in the following code:
//Define a global variable to hold http request
//object
var xmlhttp=null;
Function DoLookup()
{
//Create a valid url with user typed place value
var url = "your http handler url"? + place.value;
//Create an instance of xmlHttp
xmlhttp=new ActiveXObject("Msxml2.XMLHTTP");
if(xmlhttp)
{
//Now open a request and assign callback
xmlhttp.open("GET",url,true);
xmlhttp.onreadystatechange= FindPlaceRequestCallBack;
//Send the request
xmlhttp.send(null);
}
}
A callback function,FindPlaceRequestCallBack, is assigned to handle the response and any other state changes in the input request; the implementation of theFindPlaceRequestCallBackis as follows:
function FindPlaceRequestCallBack()
{
if(xmlhttp)
{
if(xmlhttp.readyState==4&&xmlhttp.responseText)
{
//Get the response content
var placecontent = xmlhttp.responseText;
//Just execute the response content
eval(placecontent);
xmlhttp = null;
}
}
}
The callback function receives the response text from the HTTP handler and executes the resulting JavaScript using theevalmethod. The resulting JavaScript is nothing but theShowLocation function call withFindresult matches for the input place. Next, we need to implement theShowLocationfunction:
function ShowLocation(findResults)
{
if(!findResults)
{
return;
}
//Display results
if(document.getElementById(displayplanelname))
{
document.getElementById(displayplanelname).style.visibility="visible";
document.getElementById(displayplanelname).innerHTML = findResults;
document.getElementById("place").focus();
}
}
In this function, the results are assigned to thedivelement to be displayed to the user. Your AJAX application for place lookup is now ready. With minimal effort, you can AJAX-enable your MapPoint Web Service web application to provide a great user experience.
Obviously, you can extend these functions more to optimize your client-server communication by limiting the requests to strings more than three characters in length. Also, you can implement more features such as scroll enabling with arrow keys, and mouse-select enabling in JavaScript to add more depth to the application. The sample application included in the companion material has all these features implemented in JavaScript.
Finally, because you are charged a fee for each MapPoint Web ServiceFindcall, you need to evaluate this design appropriately; a more cost-effective variation to this implementation might be to do a lookup asynchronously when the user clicks Enter, instead of performing a lookup for each character typed.
Next: Optimizing Find Call Performance >>
More BrainDump Articles
More By O'Reilly Media
|
This article is excerpted from chapter six of the book Programming MapPoint in .NET, written by Chandu Thota (O'Reilly; ISBN: 0596009062). Check it out today at your favorite bookstore. Buy this book now.
|
|