Article Author: Rahul Pitre
Introduction
Location-based services technology has come a long way from its humble beginnings as a source of approximate driving directions. It now provides mapping and route generation functionality to mobile users, tracks mobile users carrying wireless devices and supplies supplementary information from Points of Interest (POI) databases. It has spawned new classes of applications that analyze traffic and track vehicle fleets or other mobile assets in real time.
MapPoint is Microsoft’s platform for location-based services. It comprises a slew of products that generate maps, routes, and driving directions, provide points of interest, and track mobile users.
Some MapPoint based products target end-users. Streets and Trips 2005, for instance, is a desktop application to plan trips and routes, and print trip details. Its companion application, Pocket Streets 2005, lets people carry the trip details along on Windows Mobile PocketPCs and mobile phones. People who routinely get lost while driving can use a version of Streets and Trips 2005 that comes with a GPS device and gives voice directions. Those who prefer online directions can use an online version of MapPoint at MSN Maps & Directions.
Other products based on MapPoint technologies target large applications and their developers. MapPoint 2004 is a tool for developing location-enabled desktop applications. It has an ActiveX control that generates routes and maps. But its license agreement restricts using its maps in web applications. Besides, most self-respecting web applications are no longer happy with simply plopping pre-generated maps onto web pages. Their users expect customized maps and directions on the fly. MapPoint Web Service ( MWS ) is a web-service that generates maps and routes on demand. Its companion, MapPoint Location Server ( MLS ) builds on the basic MWS functionality. It allows applications to locate an enabled wireless device, and therefore the person possessing it, in real time. For example, a central office for a cable service company could track the whereabouts of its service engineers and provide customers a better time frame for service than the customary "anytime between 10:00 AM and 5:00 PM".
This article is about MWS. It is a subscription-based service that targets big customers who want to location-enable large applications. A typical application of the service is the ubiquitous "find-a-store" feature on retailer and restaurant-chain web sites. You will find several variations of the theme.
Outwardly, it may appear to you that a developer will need advanced training in spherical trigonometry, a year or two of cartography experience under there belt and plenty of luck before they can even think of developing a sophisticated location-enabled application. Nothing can be farther from the truth. Even a music-major-turned-programmer, can easily do it, thanks to MWS. All he needs is a series of well-positioned calls to MWS.
This article will introduce you to the powerful and easy-to-use features of MWS.
System Requirements
To use the sample application, you should have:
- IIS running on Windows 2000 or later
- The .NET Framework version 1.1
- VisualStudio.NET 2003
- An account to access MapPoint Web Service 3.5
Normally you must have an enterprise level account to access MWS but you can test drive the service for 45 days with an evaluation account. To get an evaluation account, go to https://MapPoint-css.partners.extranet.microsoft.com/MwsSignup/Eval.aspx. Fill out and submit the form and you should receive your account details from MWS via email in two or three days.
If you subscribe to MSDN, you are entitled to a one-year evaluation account (and 50000 live transactions) at no charge. To exercise your entitlement,, go to http://www.microsoft.com/MapPoint/msdn/msdnspec.aspx and get your MSDN trial account.
While you wait for the account details, download the MapPoint SDK from its download site and install it. The SDK is not essential for using the sample application, or any application for that matter, but it integrates MapPoint reference documentation with Visual Studio .NET 2003 help system and installs extensive samples on your machine, which can come in handy if you want to program with MWS.
Installing and Compiling the Sample Code
To install the sample, start by unzipping the sample download file. It will yield a directory named MapPoint that contains the sample web project. Then create an IIS virtual directory named MapPoint , which points to the location of the unzipped MapPoint directory.
Next, open the MapPoint directory in Windows Explorer and double click the MapPoint.sln file. The solution will open in Visual Studio.
Since MWS is a web service, you need a client-side proxy (remember, your web server is the client in this case) to access it. You would normally have to create the proxy by creating a web reference to MWS’s Web Service Definition File (WSDL file) at http://staging.MapPoint.net/standard-30/MapPoint.wsdl. I have already created the reference in the project you have downloaded, and you can verify that I have done so by expanding the Web References node in your Solution Explorer , as shown in Figure 1.

Figure 1. Web Reference to MWS s WSDL file as seen in Solution Explorer
The application will compile just fine but it will NOT run correctly until you enter your account information in the <appSettings> section of the web.config file as shown below:
<!— Enter your MWS User Id and Password below —>
<appSettings> <add key="MapPointUserId" value="Enter your user id here" /> <add key="MapPointUserPassword" value="Enter your password here" />
</appSettings>
If your web server accesses the Internet through a proxy server, you may have to update the proxyaddress of <defaultProxy> element in <system.net> section of web.config as shown below.
<! “defaultProxy
The setting is needed if your web server connects to the internet through a proxy server.
Uncomment the <defaultProxy> element below if this setting is relevant. If you face proxy related issues, please refer to the knowledge base article mentioned in the "Related Links" section at the end of the article
—>
<!—
<defaultProxy> <proxy usesystemdefault = "false" proxyaddress="http://myproxy.mydomain.com:port" bypassonlocal="true" />
</defaultProxy>
—>
Once you plug this information in, compile and run the application. Visual Studio .NET 2003 will prompt you to save a solution file ( MapPoint.sln ). Do so and you should see a web page similar to that shown in Figure 2.
The Sample Application
The sample application demonstrates some of the simplest tasks MapPoint performs. It presents a form where you enter a street address in the United States. The application validates the address. If the address is valid, i.e., if it identifies an unambiguous location, the application finds the nearest restaurant and generates an appropriately scaled map showing both the locations. It highlights the route between your location and the restaurant, and provides turn-by-turn driving directions. If the address is ambiguous, it presents intelligent choices so that you may pick the right one. If the address is fictitious or cannot be found, the application displays an appropriate message.
If you were to develop this application to be a part of a restaurant chain’s web site, you would want it to find the nearest restaurant that belonged to the chain. You would then need a comprehensive list of all of the chain’s locations. You would upload the list to the MWS web server as custom data and then use it to find the nearest restaurant.
Since you (or to be precise, I) don’t have such a list, the application simply finds the nearest restaurant of any kind. It uses the Navtech.NA datasource, an MWS data repository that provides business listings by industry codes.
The sample application has a single page, Default.aspx . It looks like Figure 2 when it first comes up and asks you to enter a street address in the United States.

Figure 2. Sample application requesting the user to enter a street address
If you enter a correct street address, it displays a map with the route and directions, as shown in Figure 3.

Figure 3. Map route and directions to the restaurant nearest to the address entered
I have referred to "ambiguous address" a couple of times and I will elaborate on it with an example. The default address that comes up with the page is 200 North Broadway, Yonkers, NY 10701. There really is a building out there on South Broadway in Yonkers, NY that bears the number 200. So the address is uniquely identifiable. But if you enter the address as 200 Broadway, Yonkers, NY 10701, it does not correspond to a physical location in Yonkers, NY. Yet, it is a plausible address because there are buildings both at 200 North Broadway and at 200 South Broadway. In such situations, MWS can provide you with possible address choices. To see this, remove the word "North" from the displayed address and click on Find Restaurant . You will see the screen in Figure 4.

Figure 4. MWS can provide a list of possible addresses, if your address is ambiguous
If you enter an address that simply does not exist and if MWS cannot find one even remotely similar to the one you entered, MWS will inform you and you will see a screen similar to the one in Figure 5.

Figure 5. Screen when the address entered is not found
MWS Basics
MWS is not a single, monolithic entity. It comprises four services: FindServiceSoap , RenderServiceSoap , RouteServiceSoap , and CommonServiceSoap . FindServiceSoap determines the locations of street addresses and latitude/longitude co-ordinate pairs. RenderServiceSoap renders a map for a set of locations. RouteServiceSoap generates routes, point-to-point directions, and identifies points of interest along the route. Finally, CommonServiceSoap provides utility functions and classes used by the other three services. MWS is just a convenient moniker for the entire bundle.
MWS has two environments – a staging environment and a production environment. From a developer’s perspective, the only difference between the two is the location of the WSDL file that specifies the location and operations of the service. Typically, developers reference the staging environment while writing and testing applications. When applications are ready for release, they simply change the WSDL references to use the production environment, used solely for tested applications of paying customers. MWS also supports SSL in both its environments.
Precise geocoded and demographic data is crucial for rendering accurate maps. MWS packages its data as repositories called datasources. You can choose datasources to suit the nature and purpose of your applications. Some datasources provide geographical data. MapPoint.NA , for instance, is a source of geographic data of US Canada, Puerto Rico and parts of Mexico. You can use it to find addresses, map locations, and plan routes in the area it covers. MapPoint.EU provides similar data for Europe. Other datasources, such as the NavTech.NA datasource used in the sample application, provide demographic and point-of-interest data. A datasource might not support all MWS features. MapPoint.World , for example, supports rendering maps of the world but can’t generate routes. MapPoint.Moon can be used to generate lunar maps but not for finding addresses. (Driving directions from New York to Paris and an address on the moon are both meaningless anyway.) You can also create custom datasources containing only the locations that are of interest to your application.
Before delving into the sample application, a quick overview of MWS objects that are necessary to understand the code is in order.
A Location object represents a physical location on the Earth’s surface (unless you are using MapPoint.Moon datascource, of course). Two of its attributes, Address and LatLong are of interest. The Address object has a FormattedAddress property which holds the complete unparsed street address of the location. It also has properties to hold constituents of the street address such as street, city and postal code. A LatLong object represents the latitude/longitude co-ordinates of the location. The location is marked on a map with a Pushpin object. A Pushpin has properties to customize its visual appearance. The sample application uses a star icon to represent your location and a fork-and-knife icon to represent the restaurant.
When you find an address or ask for nearby points of interest from a point-of-interest database, MWS returns locations to you as a FindResults collection, a collection of FindResult objects. In fact, any find operation in MWS returns FindResult objects. Each FindResult object contains a Location object and a Score associated with the location.
There are many ways to get a map of a rectangular area on the Earth’s surface. You can get it by specifying the latitude/longitude co-ordinates of the vertices of the rectangle. You can also get it by specifying latitude/longitude co-ordinates of its central point and a scale. You may choose one method over another depending on the information you have. But regardless of the method, the map you get is still the representation of the same terrestrial rectangle. In MWS parlance, the different representations of a map are called views . MWS has four types of views – ViewByBoundingLocations , ViewByBoundingRectangle , ViewByHeightWidth , and ViewByScale , all of which are descendants of MapView , an abstract class. When you don’t know the relative distances of locations, it is difficult to come up with a suitable scale or view for the map. You will not want to render the map of the entire state of New York, for example, when you want to find the nearest restaurant in New York City. MWS’s RenderService has a method called GetBestMapView() that can determine the appropriate scale for the map given a set of locations.
You specify the display characteristics of a map using the MapOptions object. It has attributes to specify rendering details such as height, width, font, and style.
You request a map from MWS by sending it all the relevant information in a MapSpecification object. The DataSourceName attribute of MapSpecification tells MWS which datasource to use. The Options attribute provides rendering options via a MapOptions object. The Pushpins attribute, a collection of Pushpin objects, specifies the location markers on the map. The Views attribute, a collection of MapView ‘s descendents, tells MWS how the map should be drawn.
MWS can render maps in two ways – as a bitmap or as a url. If you ask for a bitmap, you get one, but you may need to cache it on your end depending on the functionality of your application. If you ask for a url, MWS caches the map image on its servers and sends you a url. The map cannot stay in the cache indefinitely. It is discarded after five minutes or after ten hits, whichever event occurs first. The MapOptions object has an attribute that lets you specify whether you want the map rendered as a bitmap or as a url pointing to a cached image
Now that you are familiar with the basic terminology, it is time to peek at the code.
The Code
The application consists of a single page that has the user interface , Default.aspx , and a class that encapsulates all MWS related code, MapPointHelper . Default.aspx does not know anything about MWS. It simply makes calls to an instance of MapPointHelper , which does the work and returns relevant data to the page.
Default.aspx
When you run the application, you see the web page in Figure 3 above requesting you to enter your address. Enter an address and click on the Find Restaurant button. The first step is to see if the address that was entered is valid. That is the domain of FindService service of MWS and the page should now send the address over for validation. FindService expects the address to be in a certain format (that may seem counterintuitive to you). The following code in Default.aspx formats the address in the expected format and passes it to ValidateAndMap() function of the page.
Dim sb As New StringBuilder
sb.Append(Address1.Text)
sb.Append(", ")
sb.Append(City1.Text)
sb.Append(" ")
sb.Append(Zip1.Text)
sb.Append(" ")
sb.Append(State1.Text)
FormattedAddress = sb.ToString()
ValidateAndMap(FormattedAddress)
ValidateAndMap() invokes the ValidateAddress() function of MapPointHelper and gets the status of the validation as the return.
Dim ValidateionStatus As MapPointHelperStatus =
MyMapPointHelper.ValidateAddress(formattedAddress)
If the address is not found, Default.aspx displays a message to that effect:
Case MapPointHelperStatus.AddressNotFound Label1.Text = "This is not a valid street address. Please try again."
If the validation process determines the address to be unique, all you have to do is ask for the map and directions, and display them.
Case MapPointHelperStatus.UniqueAddressFound Image1.ImageUrl = MyMapPointHelper.GetMapUrl() Label2.Text = MyMapPointHelper.GetDirections()
The third possible outcome of the validation is that the address is ambiguous. In this case, MWS returns a list of possible addresses that it thinks you might be interested in. The page displays them in a listbox so that you may select one of them or click on the Start Over button to enter a fresh address.
Case MapPointHelperStatus.MultipleAddressesFound ListBox1.DataSource = MyMapPointHelper.AmbiguousAddresses ListBox1.DataBind() ListBox1.SelectedIndex = 0
The rest of the code in the page simply hides and shows the appropriate controls on the page depending on the result of the validation.
The code that interacts with MWS is encapsulated in the MapPointHelper class. Default.aspx first calls MapPointHelper ‘s ValidateAddress() function.
Before the application can ask MWS to validate the address, it must identify itself to MWS. Each of the three MWS services needs separate authentication. Since FindService performs the validation, the following lines of code create an instance of FindService , pass the authentication information to it and ask it to validate the address that was entered.
Dim MyFindService As New FindServiceSoap
MyFindService.Credentials = New NetworkCredential(UserId, Password)
Dim ValidationResults = MyFindService.FindAddress(FindAddressSpec)
The address passed to FindService is passed as a FindAddressSpecification object which is set up as:
Dim FindAddressSpec As New FindAddressSpecification
FindAddressSpec.InputAddress = New Address
FindAddressSpec.InputAddress.FormattedAddress = Address
FindAddressSpec.InputAddress.CountryRegion = MyCountry
FindAddressSpec.DataSourceName = MyDataSource
If FindService determines that the address does not exist, the function simply relays the information to Default.aspx via a status.
If ValidationResults.NumberFound = 0 Then ‘No matching address Return MapPointHelperStatus.AddressNotFound
If the address is unique, FindService returns a FindResult object, which MapPointHelper stashes away in a local variable for future reference and informs Default.aspx that a unique address was found.
ElseIf ValidationResults.NumberFound = 1 Then ‘This was a unique address; no ambiguity. _inputlocation = ValidationResults.Results(0) Return MapPointHelperStatus.UniqueAddressFound
If the address is ambiguous, MapPointHelper builds an ArrayList containing the possible addresses and stores it in a local variable. Default.aspx retrieves the ArrayList by reading the AmbiguousAddresses property of MapPointHelper .
Else
‘The address is ambiguous. All possible addresses are returned in
‘ValidationResults.
‘Prompt the user to select one of the addresses
Dim NoOfAddressesFound = ValidationResults.NumberFound – 1
Dim Al As New ArrayList
For i As Integer = 0 To NoOfAddressesFound
Al.Add(ValidationResults.Results(i). _
FoundLocation.Address.FormattedAddress.ToString)
Next
_ambiguousaddresses = Al
Return MapPointHelperStatus.MultipleAddressesFound
Default.aspx requests a map by calling the GetMapUrl() function of MapPointHelper which in turn asks the RenderService service of MWS. RenderService needs a MapSpecification object which is declared at the top as:
Dim mapSpec As New MapSpecification
A MapSpecification object has four important elements (among others) – DataSourceName , Options , PushPins and View . As I mentioned earlier, DataSourceName tells RenderService which data repository to look into.
MyMapSpec.DataSourceName = MyDataSource ‘MyDataSource = "MapPoint.NA"
Options specify the format, style and dimensions of the map.
MyMapSpec.Options = GetMapOptions()
PushPins represent the individual location markers on the map. MWS provides a wide selection of pushpin icons. The sample application map displays two pushpins – one for the address that was entered and the other for the nearest restaurant. Recall that after validating your address, MapPointtHelper stored its location in the _inputlocation variable for future reference. But you still don’t know where the nearest restaurant is and it is time to find that out.
‘Find the nearest restaurant
Dim NearestPoi As FindResult = GetNearestRestaurant(_inputlocation.FoundLocation.LatLong)
GetNearestRestaurant() invokes FindService to get the location of the nearest restaurant.
Dim MyFindService As New FindServiceSoap
MyFindService.Credentials = New NetworkCredential(UserId, Password)
Dim NearbyRestaurants As FindResults
NearbyRestaurants = MyFindService.FindNearby(MyFindSpec)
Notice that this is a find operation, just like finding the address was. Naturally, the object returned is of type FindResult .
Now that it has both the locations, GetMapUrl() can set pushpins for MyMapSpecification .
‘set pushpins
‘first, for the input location
ReDim Preserve StopPins(NumberOfPushpins)
StopPins(NumberOfPushpins) = GetPushpin(_inputlocation, "305") ’305 = star
‘Next, for the nearest Restaurant
NumberOfPushpins = NumberOfPushpins + 1
ReDim Preserve StopPins(NumberOfPushpins)
StopPins(NumberOfPushpins) = GetPushpin(NearestRestaurant, "113")
MyMapSpec.Pushpins = StopPins
Since the map needs to show the route between your address and the restaurant, a call to RouteService is required. This task is delegated to the GetRoute() function.
‘Set Route
MyMapSpec.Route = GetRoute(RouteEndPointLatLongs)
GetRoute() calls the CalculateSimpleRoute() function of RouteService to get the route.
Dim myRouteService As New RouteServiceSoap
myRouteService.Credentials = New NetworkCredential(UserId, Password)
Return myRouteService.CalculateSimpleRoute(latlongs, MyDataSource, SegmentPreference.Quickest)
Lastly, MyMapSpec needs to know which view to use to display the map. As discussed earlier, RenderService can help us determine what view would be the best.
‘set Views
Dim myRenderService As New RenderServiceSoap
myRenderService.Credentials = New NetworkCredential(UserId, Password)
Dim BestView As MapViewRepresentations = myRenderService.GetBestMapView(RouteEndPoints, MyDataSource)
Dim myViews(0) As ViewByHeightWidth
myViews(0) = BestView.ByHeightWidth
MyMapSpec.Views = myViews
All that remains to be done is to pass the MapSpec to RenderService and get the map.
GeneratedMap = myRenderService.GetMap(MyMapSpec)
Return GeneratedMap(0).Url
Default.aspx can now use this url to display the map.
A call to the GetDirections() function of MapPointHelper goes through individual segments of the route and sends back the associated directions to Default.aspx , which it displays via a label control.
Conclusion
This article showed you how easy it is to develop web applications with MapPoint Web servicse. MWS is feature rich and allows you to greatly customize the look and feel of your maps. The sample application barely scratches the surface of the functionality MWS provides. MapPoint SDK provides detailed examples for using MWS. If you wish to explore MWS further that is a good place to start.
Related ASP Today Content
2073

