Tuesday, March 10, 2009

Using Virtual Earth control with a Web-Service

I had created a Google Maps web-page that loaded data from a database using web-services: Denver Traffic Cameras. This post is a tutorial on how to create such a page (its basically a tutorial on how to create a web-service which can be called from java-script and then continues on to show you how to use it with the Virtual Earth map control).

note: the source code can be downloaded from - http://www.aggregatedintelligence.com/Samples/VEandWS/VEandWS.zip

1. Create an ASP.Net web site.

I used VS 2008 and .Net framework 3.5.

2. Create a web-service (extension should be ASMX)

image

This will add an ASMX file, as well as a cs file in the app_code folder. The cs file implements the web-service and the ASMX file allows the web-service to be referenced by JavaScript. (Call it WebService.asmx, so that it is easy for you to follow my code).

3. Add the attribute “[System.Web.Script.Services.ScriptService]” on the web-service.

This is required so that the service can be called from JavaScript.

4. Add a ScriptManager to the web-page.

Next, in the aspx file (called default.aspx in my example), drag a ScriptManager from the toolbox onto the page (this is the page where you will use the web-service). The script manager is required for AJAX support on the page and will allow us to reference the web-service. To add a reference to the web-service, you need to modify the script manager control so that it looks like the following code:

<asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services><asp:ServiceReference Path="~/WebService.asmx" /></Services>
</asp:ScriptManager>

5. Add a web-service method

The web-service file that was added to the App_Code folder will contain a basic implementation of a method that can be called from JavaScript and should be called “HelloWorld”. If not, add the following code to the web-service class.

[WebMethod]
public string HelloWorld() {
    return "Hello World";
}

6. Call the web-service from the web-page

Next, add the following code to the <head> section of the aspx file (this code contains the call-back function that will be called when we call the HelloWorld web service method).

<script type="text/javascript">
   // This is the callback function that
    // processes the Web Service return value.
    function SucceededCallback(callBackValue)
    {
        var RsltElem = document.getElementById("divReturnCall");
        RsltElem.innerHTML = callBackValue;
    }

</script>

Finally, in the <body><form> section of the ASPX page, add the following code, which adds a button (whose on-click handler, calls the web-service method “HelloWorld”) and a div element that will be used to display the return value from the web-service.

<input type="button" onclick="WebService.HelloWorld(SucceededCallback)" value="Call Web Service"  />
<div id="divReturnCall">
</div>

Now when you run this page, you will see a button, which when clicked, will update the div with the text that is returned by the HelloWorld web-service method.


7. Update the code, so that the web-service returns an object

Next, we will add a class that we will use to return data via the web-service.

Add the following code to the webservice.cs file (after the definition for the WebService class):

public class MyWebServiceData
{
    private string _description ="Hello World";
    public string Description
    {
        get { return _description; }
        set { _description = value; }
    }
}

8. Update the web-page code to handle the object that is being returned:

Next update the SucceededCallback in the default.aspx page with the following code:

function SucceededCallback(callBackValue)
{
    var RsltElem = document.getElementById("divReturnCall");
    RsltElem.innerHTML = callBackValue.Description;
}

The code now uses the Description property on the returned value to update the web-page.


9. Introduce Virtual Earth into the page

Now, lets add a Virtual Earth map control to the page.

In the <head> add a reference to the VE javascript file:

<script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>

Also add the following code to the in the script section of the page containing the SucceededCallback method.

var map = null;
function GetMap() {
    map = new VEMap('myMap');
    map.LoadMap();
    map.SetCenterAndZoom(new VELatLong(39.729466, -104.982005), 10);
}

In the <body> section of the page, add a div with ID “myMap” that will contain the map.

<div id='myMap' style="position:relative; width:500px; height:500px;"></div>

Finally, add the onLoad event to the <body> of the page (the onLoad event will call the method which will load the VE map into the page)

<body onload="GetMap()">

Your page should now look like this:

<%@ 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 xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
     <script type="text/javascript" src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2"></script>   
     <script type="text/javascript">
            // This is the callback function that
            // processes the Web Service return value.
            function SucceededCallback(callBackValue)
            {
                var RsltElem = document.getElementById("divReturnCall");
                RsltElem.innerHTML = callBackValue.Description;
            }
            var map = null;
            function GetMap() {
                map = new VEMap('myMap');
                map.LoadMap();
                map.SetCenterAndZoom(new VELatLong(39.729466, -104.982005), 10);
            } 
        </script>
</head>
<body onload="GetMap()">
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services><asp:ServiceReference Path="~/WebService.asmx" />
        </Services>
    </asp:ScriptManager>
    <div id='myMap' style="position:relative; width:500px; height:500px;"></div>
<div id="divReturnCall"></div>
    <input type="button" onclick="WebService.HelloWorld(SucceededCallback)" value="Call Web Service"  />
    </form>
</body>
</html>

Test the page out: When the page loads, it should show you the Virtual Earth map centered over Denver.


10. Update the web-service so that it returns objects that contain push-pin information:

The web-service needs to return an array of objects which will contain the location information (latitude,longitude) of the push-pins to be added to the web-page.

Change the code for “MyWebServiceData” so that it has properties for all the information needed to create a push-pin (latitude, longitude, title and description):

public class MyWebServiceData
{
    public string Description {get;set;}
    public double Latitude { get; set; }
    public double Longitude { get; set; }
    public string Title { get; set; }
    public MyWebServiceData(string title, string description, double lat, double lon)
    {
        Title = title;
        Description = description;
        Latitude = lat;
        Longitude = lon;
    }
}

Also, update the HelloWorld web-service method so that it returns an array of the MyWebServiceData objects: (I have prefilled it with push-pins of a couple of landmarks in Denver)

[WebMethod]
public MyWebServiceData[] HelloWorld()
{
    MyWebServiceData[] cv = new MyWebServiceData[2];
    cv[0] = new MyWebServiceData("Push pin 1", "City and County of Denver", 39.740755, -104.990201);
    cv[1] = new MyWebServiceData("Push pin 2", "Colorado State Capitol", 39.739336, -104.984858);
    return cv;
}

11. Update the web-page, so that it can take advantage of the push-pin information that the web-service now returns.

In the ASPX file, update the <script> in the web-page to the following code:

<script type="text/javascript">
        // This is the callback function that
        // processes the Web Service return value.
        function SucceededCallback(callBackValue) {
            //send the data to the AddPushpin method
            AddPushpin(callBackValue);
            var RsltElem = document.getElementById("divReturnCall");
            RsltElem.innerHTML = "Pushpins have been loaded";
        }

        var map = null;
        function GetMap() {
            map = new VEMap('myMap');
            map.LoadMap();
            map.SetCenterAndZoom(new VELatLong(39.739039, -104.988613), 15);
        }

        function AddPushpin(callBackData) {
                //load the data from callBackData in VEShape objects and load into the map, but first clear the old pushpins
            map.DeleteAllShapes();
            for (i = 0; i < callBackData.length; i++) {
                var shape = new VEShape(VEShapeType.Pushpin, new VELatLong(callBackData[i].Latitude, callBackData[i].Longitude));
                shape.SetTitle(callBackData[i].Title);
                shape.SetDescription(callBackData[i].Description);
                map.AddShape(shape);
            }
        }
</script>

The code, adds a method called “AddPushpin”, which creates and adds the pushpins sent back by the web-service. The AddPushpin method is called from the call-back method “SucceededCallBack”, which updates the old div “divReturnCall”, with a success method, once the push-pins have been added.

Now, when you click the button, the web-service method “HelloWorld” gets called, which returns an array of pushpin objects. The returned objects are sent to the call-back method “SucceededCallBack”, which passes it along to AddPushpin, where the code iterates over the array, adding each contained object as a push-pin.

image


Further things to do:

Now that I have shown you how to use a web-service with the Virtual Earth map control, you can modify the web-service method “HelloWorld” to return data from a database. This will allow you to customize your site easily.

You can also swap out the Virtual Earth control and instead use the Google Maps control.

Downloads:

The solution can be downloaded from: http://www.aggregatedintelligence.com/Samples/VEandWS/VEandWS.zip

Reference:

5 comments:

Anonymous said...

Great article i was use it on my current project.

Rajnish
http://ignou-student.blogspot.com

Thusitha said...

Excellent work.. and great explanations..

Femi George said...

Great article!!...

I have one interesting question...

What will i need to do to adapt this code to work with the Bing Silverlight Control?

Thanks

iimchuckles said...

Just a quick note.
If you plan on loading a bunch of points on the client side you may want to load them into an array of shapes and then add them all at once. Helps speed things up a bit.

Anonymous said...

Excellent tutorial