I’ve been working on this one for a while and it kind of completes the basics for getting started with the Virtual Earth Web Service. The Routing Service in VEWS allows for route calculation and itinerary creation. The following will get you started using the routing service. In this sample I’ll instantiate the service request, pass the points into an array, set options for the route object, get the route object back and parse the information into a table for viewing.
First things first, add a web reference to the route service.
Next, the following code will provide you with the route itinerary starting at lat/lon (40, –120) then stopping for some Starbucks coffee at lat/lon (40.5, –120.5) and ending at lat/lon (41, –121). The inline documentation should help explain what’s happening. The ASPX and Code-behind are available below.
////////////////////// //Route.ASPX.CS //////////////////////
using System; using System.Web; using System.Web.UI.WebControls; using VEWSX.TokenService; using VEWSX.RouteService;
namespace VEWSX { public partial class Route : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //Labels are hidden when the page loads Label3.Visible = false; Table1.Visible = false; }
protected void Button1_Click(object sender, EventArgs e) { //Authenticate and get a token string myToken = Authenticate.Authentication(Page.Request.UserHostAddress); //Instantiate Route Request RouteRequest myRouteRequest = new RouteRequest(); myRouteRequest.Credentials = new RouteService.Credentials(); myRouteRequest.Credentials.Token = myToken; //Create an array of points (this could also be addresses, versus lat/lons RouteService.Waypoint[] waypoints = new RouteService.Waypoint[3]; waypoints[0] = new RouteService.Waypoint(); waypoints[0].Description = "Start"; waypoints[0].Location = new RouteService.Location(); waypoints[0].Location.Latitude = 40; waypoints[0].Location.Longitude = -120; waypoints[1] = new RouteService.Waypoint(); waypoints[1].Description = "Starbucks"; waypoints[1].Location = new RouteService.Location(); waypoints[1].Location.Latitude = 40.5; waypoints[1].Location.Longitude = -120.5; waypoints[2] = new RouteService.Waypoint(); waypoints[2].Description = "End"; waypoints[2].Location = new RouteService.Location(); waypoints[2].Location.Latitude = 41; waypoints[2].Location.Longitude = -121; //Pass the array into the Route Request object myRouteRequest.Waypoints = waypoints; //Creation Route options RouteOptions myRouteOptions = new RouteOptions(); //Set travel mode - Driving or Walking myRouteOptions.Mode = TravelMode.Driving; //Set the optimization type - MinimizeDistance or MinimizeTime myRouteOptions.Optimization = RouteOptimization.MinimizeDistance; //Set the use of traffic conditions - TrafficBasedRouteAndTime, TrafficBasedTime, or None myRouteOptions.TrafficUsage = TrafficUsage.None; //Pass the Route Options to the Route Object myRouteRequest.Options = myRouteOptions; //Instatiate Route Service Request RouteService.RouteServiceClient myRouteServiceClient = new RouteService.RouteServiceClient(); //Instantiate Route response RouteService.RouteResponse myRouteResponse; //Calculate the Route myRouteResponse = myRouteServiceClient.CalculateRoute(myRouteRequest); //Instantiate Route Leg RouteService.RouteLeg myRouteLeg; //Create directions, parse them and put them in a table string directions = ""; TableRow tRow = new TableRow(); Table1.Rows.Add(tRow); TableCell tCell0 = new TableCell(); tCell0.VerticalAlign = VerticalAlign.Top; tRow.Cells.Add(tCell0); tCell0.Text = ""; for (int i = 0; i < myRouteResponse.Result.Legs.Length; i++) { myRouteLeg = myRouteResponse.Result.Legs[i];
for (int j = 0; j < myRouteLeg.Itinerary.Length; j++) { directions = directions + myRouteLeg.Itinerary[j].Text + " (" + Math.Round(myRouteLeg.Itinerary[j].Summary.Distance, 2) + " miles, " + (myRouteLeg.Itinerary[j].Summary.TimeInSeconds / 60) + "mins)" + "<br/>"; } }
tCell0.Text += directions; Label3.Visible = true; Table1.Visible = true; } } }
////////////////////// //Route.ASPX //////////////////////
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Route.aspx.cs" Inherits="VEWSX.Route" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>Untitled Page</title> </head> <body> <form id="form1" runat="server"> <br /> <p> <asp:Button ID="Button1" runat="server" onclick="Button1_Click" Text="Get Route" /> </p> <asp:Label ID="Label3" runat="server" Text="Results"></asp:Label> <br /> <asp:Table ID="Table1" runat="server" Height="387px" Width="444px"> </asp:Table> </form> </body> </html>
Here’s what you should end up with:
Pretty simple, but hopefully this will provide you with the information you need to get your routing application up and running. I didn’t do error handling, so make sure you include that with your application. Specifically, when you’re making your service calls.
CP
I get an error running the code.
I gets a tokeb but fails getting the route:
RouteService.RouteResponse routeResponse = routeService.CalculateRoute(routeRequest);
The reported error is
- ex {"An error occurred while processing the request."} System.Web.Services.Protocols.SoapException
Drilling into ex (The Soap exception) it seems that validation isn't the problem:
InnerXml "<ResponseSummary xmlns=\"http://dev.virtualearth.net/webservices/v1/common\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"><AuthenticationResultCode>ValidCredentials</AuthenticationResultCode><Copyright>...Copyright><FaultReason>An error occurred while processing the request.</FaultReason><StatusCode>ServerError</StatusCode><TraceId>b79b0a7db86b41a8883f92dff7c69375|808</TraceId></ResponseSummary>"
?????????????
I get the same error. I can get the routing service to work from an ASP.NET webpage, but when I try to access it from a class library in SQL Server 2008 I get the 'An error occurred while processing you request' thrown from the CalculateRoute method, with no further details. I am getting the token generated ok because I can use the geocoding service from within the same library.... was this ever resolved?
Don't know if it's relevant or not, but when I create the ASP.Net page in VS2008, I add a service reference to the routing service which automatically generates a RouteServiceClient class. When I create a class library for importing into SQL Server I have to manually create a proxy for the service using wsdl.exe, which instead generates a RouteService class...
I don't understand why the name differs, although the class appears to be identical.
It's just how WCF handles the request package.
Hmm. This could be a number of things. Are you running VS 2008 or 2005? Are you adding VEWS as a service or web service? Could be a lot of reasons for this error.
If we have a start point, an end point and several points in between, is it possible to calculate the shortest route from start to end that passes through the mid-points in any order.
I know this is an NP complete problem (travelling salesman), so our only way to solve it is to get as much info from bing maps as we can, and then make educated best guesses. Otherwise it would take to long to compute.
The dynamic programming approach is not valid because we don't have the whole graphs of distances between addresses. But you do!
Thanks!
hi
your unit is wrong!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
default is Kilometer!!!!!!!!!!!!!!!!!!!!!!!!
not Miles!!!!!!!!!
Math.Round(myRouteLeg.Itinerary[j].Summary.Distance, 2) + " miles "
Math.Round(myRouteLeg.Itinerary[j].Summary.Distance, 2) + " kilometer "
You get a Soap exception if you do not state that the waypoint location lat and longitude have been specified.
waypoints[0].Location.LatitudeSpecified = true;
waypoints[0].Location.LongitudeSpecified = true;
This will enable Chris's code to work.
Edan