Getting a Map with the Virtual Earth Web Service

The most basic element of Virtual Earth – maps. The Virtual Earth AJAX control is pretty simple because you could just copy and paste code into notepad, save it and run it in a browser. Well, the Virtual Earth Web Service (VEWS) is a bit of a different animal. It uses WCF and WSDL to specify service pointers of where you should be getting maps, directions, YP and Collections, and routes. I figured it would be helpful, what with my deep background in MapPoint Web Service which has a similar architecture, to provide some help on how the Virtual Earth Web Service works. So, over the next few weeks I’ll post some (hopefully) helpful samples that will get you past some sticking points. We’ll start with just getting a map. I should mention that because I work at Microsoft, these samples will be in ASP .Net (C#), so hopefully understanding the logic will help you translate to whatever language you’re working with. If you only do JavaScript / Web Development, you’re going to need some more books, because you have some learning to do.

With the VEWS, it is required that all users authenticate. So, you’ll need to sign up for a developer account, then authenticate your usage with our HTTP Digest authentication scheme.

First thing we’ll need to do is add the Imagery Service. This uses Windows Communication Foundation (WCF), which is “a set of .NET technologies for building and running connected systems. It is a new breed of communications infrastructure built around the Web services architecture.” Ohhh, scary. Uh, no. Basically, it makes it easier for you to not have to worry about where to make your service calls to.

Add the Imagery Service
You can add the imagery service in Visual Studio by going to Website | Add Service Reference and entering the imagery service URI into the address box, then hitting go. It should pull up the reference points in the service with two supported methods (aka Operations) – GetImageryMetaData() and GetMapUri(). Give it a name at the bottom – I named mine ImageryService.

image

Add New Web Form
You’ll need a web page to contain your map, so add a web form to your project – Website | Add New Item | Web Form. I named mine Map.aspx.

Add Image to Your Web Form
VEWS returns the URI for a map image. So, you’ll want to have an image placeholder there. Do this by dragging an image object from the toolbox onto your web form. You can resize it to the size you need by dragging the corners.

Authenticate
I’m not going to show you how to authenticate here, but I thought it important to point something out. Although this is a server request, the authentication still requires a token. That wouldn’t be a challenge, but the token requires the user’s IP so here’s how to do it.

I create a class called “Authentication.cs”

In the class I put the authentication I wrote about in my Authentication and Tokens with Virtual Earth post except for one change.

Authentication.cs

using VEWSStaging;

/// <summary>
/// Authenticating for VE Tokens
/// </summary>
public class Authentication
{
public static string strVEWSToken;
public static string Authenticate(string strIP)
{
  CommonService commonService = new CommonService();
  commonService.Url = “
https://common.virtualearth.net/find-30/common.asmx”;
  commonService.Credentials = new System.Net.NetworkCredential(“XXXX”, “YYYY”);

  // Create the TokenSpecification object to pass to GetClientToken.
  TokenSpecification tokenSpec = new TokenSpecification();

  // Use the Page object to retrieve the end-client’s IPAddress.
  tokenSpec.ClientIPAddress = strIP;

  // The maximum allowable token duration is 480 minutes (8 hours).
  // The minimum allowable duration is 15 minutes.
  tokenSpec.TokenValidityDurationMinutes = 480;

  // Now get a token from the Virtual Earth Platform Token service.
  strVEWSToken = commonService.GetClientToken(tokenSpec);
  return strVEWSToken;
}
}

We’ll get the IP in the from the Maps.aspx page in the next step.

Requesting a Map
Now, I used most of the code from the SDK so it would help you longer term – teach a man to fish….. Also, I don’t use error handling, so for production applications you definitely want to add checks. Here’s the code that works for authenticating via my Authentication Class and passing the IP (UserHostAgent) to get the token (yes, token is required). I set the options for the map (center point, zoom level, map style, image height and image width) then request the URI for the map. You’ll pass that URI down into the image you dropped on your web page, and you’re done!

Map.aspx

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”Map.aspx.cs” Inherits=”Map” %>

<!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>VEWS Map</title>
</head>
<body>
    <form id=”form1″ runat=”server”>
    <div>
    </div>
    </form>
    <asp:Image ID=”Image1″ runat=”server” Height=”480px” Width=”600px” />
</body>
</html>

Map.aspx.cs

using System;
using System.Collections;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using ImageryService;

public partial class Map : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
  string myToken = Authentication.Authenticate(Page.Request.UserHostAddress);
  ImageryService.MapUriRequest myMapURIRequest = new MapUriRequest();
  myMapURIRequest.Credentials = new ImageryService.Credentials();
  myMapURIRequest.Credentials.Token = myToken;
  myMapURIRequest.Center = new ImageryService.Location();
  myMapURIRequest.Center.Latitude = 37.42196783438708;
  myMapURIRequest.Center.Longitude = -122.084039747715;

  ImageryService.MapUriOptions myMapURIOptions = new ImageryService.MapUriOptions();

  myMapURIOptions.Style = ImageryService.MapStyle.AerialWithLabels;
  myMapURIOptions.ZoomLevel = 17;
  myMapURIOptions.ImageSize = new ImageryService.SizeOfint();
  myMapURIOptions.ImageSize.Height = (int)Image1.Height.Value;
  myMapURIOptions.ImageSize.Width = (int)Image1.Width.Value;

  myMapURIRequest.Options = myMapURIOptions;

  ImageryService.ImageryServiceClient imageryService = new ImageryService.ImageryServiceClient();
  ImageryService.MapUriResponse myMapURIResponse= imageryService.GetMapUri(myMapURIRequest);
  string MapURI = myMapURIResponse.Uri;

  Image1.ImageUrl = MapURI; 
}
}

I did this in the Page_Load method, but you can certainly request a map from any web form object and event. When it’s all said and done, you get this lovely aerial photo with labels returned to you in .JPEG format and rendered onto a blank page. You’ll want to just build your application around it as needed.

image

I’ve been getting the question recently about the advantages of VEWS over AJAX. Perhaps this is a post in and of itself, but from a feature perspective:

  1. VEWS (SOAP) is a server to service model (AJAX is client to service). This means you’ll get the map image before your web page is sent to the client. You can control the image and ensure it’s there before sending it down to the client.
  2. VEWS provides static images (on the fly), so you can insert them anywhere that support HTTP requests – mobile devices, JavaScript disabled browsers – or insert them into other documents such as PDFs.
  3. If you’re using MapPoint Web Services, you can finally move over to a similar architecture with almost complete feature parody, but get the “pretty” maps and aerial photos.
  4. JavaScript is a lightweight scripting language which is great for fast web development, but for heavier applications requiring back end integration you can use VEWS with .Net, Java and any other language that works with HTTP.

SOAP is so clean.

CP

Join the conversation

20 comments
  1. Anonymous

    Chris,

    The URL for the image seems to have a placeholder for the token:

    myMapURIResponse.Uri

    {token}

    Are we supposed to manually replace this with the actual token?

    John.

  2. Chris Pendleton

    John – you don’t need to replace it. We’re using the token you send in the response to track the transaction.

    CP

  3. Chris Pendleton

    John – you don’t need to replace it. We’re using the token you send in the request to track the transaction.

    CP

  4. Anonymous

    Hi Chris

    Thanks for your webcast!

    Just a follow up on this post.

    I built a mobile website that display a map using the method you presented. Now I would like to add some arrows to pan the map.

    So I was wondering: is there any way to get the bounding rectangle of an image returned by the VEWS?

    That way I could find the coordinates of the sides to recenter my current view.

    Thanks!

    Johann

  5. Anonymous

    Thanks for the code! Your examples are a great jump start for me. I am new to working with Virtual Earth and my colleague and I were checking out these samples. We had to modify your example to use ImageryService instead of ImageryServiceClient to get it working for us using VS 2005 and the common service staging url. Also had to set the Latitude and LongitudeSpecified to true for the center in the URI request as well as the Height and WidthSpecified attributes to true for the image size in the URI options. I am unclear as to why we would have to do it this way though. Any clarification would be appreciated.

  6. Anonymous

    Chris,

    In addition to what jolebas asked:

    Without bounding rectangle info we get little more then a nice picture back from the imageryservice.

    So i thought, if we cant get it back from the service maybe in the request…

    So i tried this:

    mapUriRequest.UserProfile = new UserProfile();

    mapUriRequest.UserProfile.DeviceType = DeviceType.Desktop;

    Rectangle bounds = new Rectangle();

    bounds.Northeast = new Location();

    bounds.Northeast.Longitude = 60;

    bounds.Northeast.Longitude = 7;

    bounds.Southwest = new Location();

    bounds.Southwest.Latitude = 50;

    bounds.Southwest.Longitude = 3;

    mapUriRequest.UserProfile.MapView = bounds;

    But then the response returns a 404 not found.

    Can you please tell how can this be done? Am i overlooking something?

    (Cant be done would also be an answer!)

    Thanks,

    Dirk

  7. Chris Pendleton

    @Dirkgalien – I’ve verified that there’s currently no way to do this. We’ll have to get this into an upcoming release.

    CP

  8. Anonymous

    Hello!

    I need to get a BirdsEyeView Map for a specific location (I have the latitude and the longitude of the location).

    I have used the GetImageryMetadata function.

    My problem is that the Url that this function is returning me is composed from multiples titles.

    I have put together this titles and composed the image map.

    But my problem is that I don’t know how to get the url image for my location, not the whole map. image

    I want only my specific location image.

    The size of the image must be 240px Height and 320px Width.

    Could you please help me with this?

    Thank you,

    Mihaela.

  9. Chris Pendleton

    Mihaela,

    We don’t support this feature just yet. Right now, we just return the tiles.

    CP

  10. Anonymous

    Hello Chris,

    Thank you for your answer.

    Mihaela.

  11. Anonymous

    Mihaela,

    I have created a utility class in C# that takes a desired boundary area & image size returns an object with the VE zoom level required to fit that boundary, the centre point & the lat/lng of the corners of the image.

    I agree, it would be lovely to get this from the map service, but it’s a good second best.

    I’m too busy to try & blog about it now, but mail me (my details are in my profile) and I’ll send you the code.

    Ben

  12. Anonymous

    First, thank you Chris for the code it works fine. It was very helpful for me to getting started with the VE Imagery Service.

    I use the VE Web Service (ImageryServiceClient) and therefrom the GetMapUri Method to get a static Map of an Arial Imagery.

    But know I’ve got a problem. I’ve lat/long of the corners of a location and the Image size for the Arial Image I want. I could calculate the center point of this location but I don’t know the VE Zoomlevel, which is required to fit that boundary rather the corners.  

    Is there any possibility to calculate the Zoomlevel for the static map I want?

    Or has anybody else another idea to solve my problem?

  13. Chris Pendleton

    Hi Solero,

    We don’t return this right now. We’ll include it in a future release.

    CP

  14. Anonymous

    I kept getting some image size (height/width) = 0 errors so I added some specoified tags which solved it.

           myMapURIOptions.ImageSize.Height = (int)Image1.Height.Value;

           myMapURIOptions.ImageSize.Width = (int)Image1.Width.Value;

           myMapURIOptions.ImageSize.WidthSpecified  = true;

           myMapURIOptions.ImageSize.HeightSpecified = true;

           myMapURIRequest.Options = myMapURIOptions;

           ImageryService.ImageryService imageryService = new ImageryService.ImageryService();

  15. Anonymous

    Thank you for the quick answers.

    I’ve posted my question on the MSDN Virtual Earth Forum too and got from Richard_Brundritt these link:

    http://rbrundritt.spaces.live.com/blog/cns!E7DBA9A4BFD458C5!488.entry

    Perhaps somebody helps it too!

  16. Anonymous

    Ben,

    Can you please send me your details? I am interested in the c# utility class for taking a box and getting an image.

  17. Anonymous

    Bing is  a  really  overlord!!    support Bing~~

  18. nparian

    Hello,

    I see that it is not possible to specify the bounding rectangle for the map, however is it possible to get the bounding rectangle of the returned image after the web service call?

    If not, when is the next release scheduled and will it include specifying or retrieving the bounding rectangle?

    I could create the image with a known bounding rectangle by using the GetImageryMetadata call, however that method seems more of a hack.

    Thanks,

    Nick

Comments are closed.