Introduction
The ability to send asynchronous HTTP requests using the XMLHttpRequest object is at the roots of Ajax. It opens interesting scenarios such as the possibility to perform data access in the background, while the user interface remains always responsive to user inputs.
A whole category of web applications, called mashups, takes this approach to its limits. They rely almost entirely on external data sources to access and manipulate data. Often, a mashup hasn’t even got a local data store. All the data is accessed through remote web services and then combined and presented to the user.
However, here’s where life gets a little tricky. By default, it’s not possible to make a “cross-domain” HTTP request to a remote web server using the XMLHttpRequest object, without violating a security policy enforced by browsers.
Cross-domain Requests
What is a “cross-domain” request? And when exactly do we violate the domain bounds? In general, each of the following actions generates a cross-domain request and thus is blocked by the browser:
- A change in the domains. http://www.mywebsite.com cannot access http://www.yourwebsite.com.
- A change in the protocol. For example, http://www.mywebsite.com cannot make a call to https://www.mywebsite.com.
- A change in the port number. http://www.mywebsite.com:8080 cannot make a call to http://www.mywebsite.com:8088.
- A change in the sub-domain. http://mail.mywebsite.com cannot access http://calendar.mywebsite.com.
While this may appear as a real show-stopper, it’s instead a life-saver to protect our web applications against a variety of malicious attacks. Said that, it’s true that most browsers allow tweaking some configuration settings to make certain cross-domain calls succeed. However, this should be evaluated carefully due to potential security issues.
As a consequence, Figure 1 illustrates what happens if we try to send an Ajax request to a remote web server in order to get some data.
Figure 1: Browsers block cross-domain requests made with the XMLHttpRequest object.

The Proxy Technique
The technique that we’re going to illustrate in this article is widely used and involves our local web server (that is, the server that serves our pages) as the middle man between the browser and the remote server. The idea is illustrated in figure 2.
Figure 2: The local web server can be used to make a cross-domain call succeed.

The reasoning is simple: supposing that our web server doesn’t enforce any cross-domain policy, we delegate to it the execution of the request. That is, we don’t make the request directly from the browser. Instead, we make the Ajax request to our web server that, in turn, makes another request to the remote server. Once the remote server sends a response, we process the data on the local server and, finally, return the results back to the client where they are processed in the callback function.
An approach to implement this technique is to create a local web service that acts as a proxy of the remote data service. In other terms, we use the web methods exposed by the local web service to access the remote service. To shed some light on this mechanism, we are going to build a very simple mashup that uses remote services to display data on a map.
A Very Simple Mashup
Since Ajax has been adopted by web developers, maps have been widely used to display localized data. In the following example, we are going to build a simple mashup that uses the Virtual Earth API and the Yahoo! Geocode service to mark the position of Paris, a beautiful city located in France, on a world map.
The data we need are provided by two different services. Specifically, we use the Virtual Earth API to display the world map and the Yahoo! Geocode service to retrieve the coordinates (longitude and latitude) of a geographical location. Figure 3 shows our very simple mashup up and running.
Figure 3: A simple mashup that combines data from Virtual Earth and Yahoo! Geocode.

While using the Virtual Earth API is a matter of downloading a JavaScript file in the browser, accessing the Yahoo! Geocode service requires us to make a cross-domain call. Therefore, this is the strategy that we’ll follow:
- Setup a local ASP.NET web service. The purpose of the local web service is to proxy the Geocode service. Since it’s a local web service, we can invoke web methods from the client side without violating the browser’s security policy.
- Make the cross-domain request from the local web service - that is, from the local server - and send the processed results back to the client.
- Write the
JavaScript code to invoke the local web service and get the Geocode data. Finally, display the geographical data on a map. As we’ll see in a moment, ASP.NET Ajax makes this task simple and straightforward. Before turning the theory into practice, let’s do a quick overview of the remote services that we’re going to access in our mashup.
The Virtual Earth API
Virtual Earth is the Microsoft’s mapping engine. To use the Virtual Earth API, we have to reference a JavaScript file in our web page. With the Virtual Earth API, we are able to display localized data on a world map. The official Virtual Earth website is located at: http://local.live.com.
If you need a reference for the Virtual Earth API, an interactive SDK can be found at: http://dev.live.com/virtualearth/sdk/. Be sure to check also http://www.viavirtualearth.com for additional resources and articles.
The Yahoo! Geocode Service
We can use the Yahoo! Geocode service to retrieve the coordinates (longitude and latitude) of a geographical location. To invoke the service, we must send a HTTP GET request to a specific URL. In the querystring, we specify some parameters relative to the location we are interested in. For example, the following URL will return the geographical coordinates for the city of Paris, located in France:
http://api.local.yahoo.com/MapsService/V1/geocode?appid=YahooDemo&%20city=Paris&state=France
Note that the first querystring parameter is called appid. Most online APIs require that you register and request a personal key through which you can access the remote web services. The Yahoo! Geocode service, instead, doesn’t require a personal key because it limits the number of queries per IP address.
If we paste the previous URL into the browser, we will get back a response with the following XML data:
As you can see, the XML data contains Latitude and Longitude elements. Their values are the latitude and longitude coordinates that we requested.
Now that we have introduced the web services that we are going to use in our little mashup, let’s start writing some code. First of all, we need to create the local ASP.NET web service and configure it for ASP.NET Ajax. This will make us able to easily invoke web methods on the client side using JavaScript.
Ajax-enabling an ASP.NET Web Service
With ASP.NET Ajax, we can invoke web methods defined in a local ASP.NET web service and process the results using JavaScript on the client side. Listing 1 shows the code for an ASP.NET web service called GeocodeService. The code is contained in a file called GeocodeService.asmx, located in the root directory of our ASP.NET Ajax enabled website.
Listing 1: Code for the local ASP.NET web service
The GeocodeService class derives from the base WebService class. It contains a single web method called Geocode. As usual, the web method is decorated with the [WebMethod] attribute. The purpose of this method is to make a HTTP request to the real Yahoo! Geocode service and return a Location object with the information returned from the remote service.
The web method accepts the same parameters passed to the Yahoo! Geocode service. It also returns the same results, though encapsulated in a custom Location object. For this reason, the Geocode web method is “proxying” the remote service to the local server, making us able to access it.
The code for the class that defines the Location object returned by the web method is shown in listing 2.
Listing 2. Code for the Location class
Now, let’s discuss what’s needed to configure the web service for ASP.NET Ajax. The process is straightforward and consists of two steps:
- The first thing we have to do is decorating the
GeocodeService class with the [ScriptService] attribute, as shown in listing 1. The [ScriptService] attribute instructs the ASP.NET Ajax engine to generate the JavaScript code for calling the web methods on the client side.
- Secondly, we have to reference the web service in the
ScriptManager control. This will make ASP.NET request the JavaScript code generated by the GeocodeService. The JavaScript code is called the web service client proxy.
In this article, we won’t go deep into the inner workings of the ASP.NET Ajax web service proxy, but there are two main advantages in configuring a web service for ASP.NET Ajax.
The first, main benefit is that we can invoke web methods as if they were JavaScript functions. Again, this is an application of the proxy pattern. In the same manner as we are proxying the remote service to a local web service, ASP.NET Ajax is making the local web service accessible from the client side using JavaScript.
The second, implicit advantage is that we can process the method results using JavaScript. Interestingly, what is sent to the browser after the call to the Geocode web method is the Location object serialized using the JSON data format.
Inside the Geocode web method we find a call to the static Geocode method of the YahooProvider class. This method contains the actual code for invoking the Geocode service. The YahooProvider class is meant to encapsulate the code to access various Yahoo! APIs and not only the Geocode service. In this way, we can selectively choose which functionality we want to make accessible through web services.
Listing 3 shows the code for the YahooProvider class. For simplicity, the code contains only the logic for sending a HTTP request to the Yahoo! Geocode service and processing the XML data returned.
Listing 3. Code for the YahooProvider class
The YahooProvider class contains a public Geocode method and a private GetWebRequest method. The Geocode method contains the logic for sending a HTTP GET request to the Yahoo! Geocode service and processing the XML data returned. The HTTP request is built by the GetWebRequest method, which uses the location parameters and the standard Geocode service URL (stored in the static GeocodeUriFormat string) to build the request’s URL and return a WebRequest object.
Once the response is received, the XML data is processed with a XmlTextReader instance. As you can see, we are extracting the values of the Longitude and Latitude elements and parsing them as doubles. Since the Geocode query can return multiple results, we are considering only the first one for simplicity. Finally, we use the parsed values to build a Location object and return it.
This completes the setup of the local web service on the server side. Now, let’s move to the client side and put the pieces together.
Making the Cross-domain Request
Finally, we are able to invoke the Yahoo! Geocode service from our web page. As explained, we delegate this task to the Geocode method of the local ASP.NET web service. The web method returns the Location object serialized in JSON format. At this point, we access the returned data in order to display a pushpin on a Virtual Earth map. The code is embedded in the ASP.NET page shown in listing 4.
Listing 4. Code for the ASP.NET mashup
As usual, every ASP.NET Ajax page contains a ScriptManager control. Inside the ScriptManager control, we are referencing the script file with the Virtual Earth API. Also, we need to reference the GeocodeService web service. This is done by declaring a ServiceReference element inside the Services element of the ScriptManager.
The JavaScript code inside the script tag is responsible for calling the Geocode method of the local web service. Note how we are able to invoke the web method as a method of a client GeocodeService object. This is possible thanks to the JavaScript code generated by ASP.NET Ajax and sent to the browser when we referenced the web service in the ScriptManager. The client Geocode method accepts the same arguments of the corresponding Geocode web method plus two callback functions. The first one, onGeocodeComplete, is called as soon as the web method returns. The second one, onGeocodeFailed, is called if something goes wrong during the processing of the request.
In the onGeocodeComplete function, we can access the serialized Location object returned by the web method. This object is stored in the result variable passed to the callback. The serialized object has two properties called Latitude and Longitude, as in the server Location class. The values of these properties are used to build a VELatLong object, which is required by Virtual Earth to add a pushpin to the map. The pushpin object is constructed with the VEPushpin constructor and added to the map with the AddPushpin method. The final statement is a call to the SetCenter method, which centers the map at the coordinates stored in the VELatLong object. All these methods are part of the Virtual Earth API.
Finally, let’s give a look at figure 4, which shows what happens behind the scenes when we send an Ajax request to the local ASP.NET web service. Note how the response sent back to the browser contains the JSON-serialized Location object returned by the Geocode web method. To monitor the HTTP traffic we have used Firebug, a nice add-on for the Firefox browser.
Figure 4: The asynchronous call to the Geocode service returns a JSON-serialized Location object.

Resources
Check the official documentation topics to learn more about the ASP.NET Ajax asynchronous communication layer:
http://ajax.asp.net/docs/overview/AsynchronousLayerOverview.aspx
Firebug is a powerful add-on for Firefox that allows debugging the HTTP traffic and much more. You can download it from http://www.getfirebug.com.
Summary
In this article, we have seen how to make a cross-domain call by proxying it to a local web service. With ASP.NET Ajax, we can configure an ASP.NET web service and call its web methods from the client side using JavaScript. Also, complex types returned by web methods are serialized using the JSON data format and can be processed on the client side. To illustrate these concepts, we have used the Virtual Earth API and the Yahoo! Geocode service to build a simple mashup that displays a pushpin on a Virtual Earth map.
Download
SimpleMashup
About Alessandro Gallo
 |
Alessandro "Garbin" Gallo is a Microsoft MVP in the Visual ASP/ASP.NET category and a .NET developer/consultant. He is a contributor for the Ajax Control Toolkit project, owned by Microsoft. Alessandro won the Grand Prize at the "Mash-it-up with ASP.NET AJAX" contest held by Micr...
This author has published 23 articles on DotNetSlackers. View other articles or the complete profile here.
|
You might also be interested in the following related blog posts
SharePoint 2007 Web Services and Forms Authentication
read more
How to... use Class Libraries with ASP.NET AJAX like AjaxPro
read more
New Best Practice: Ajaxifying UserControls
read more
Authentication and Session
read more
The Ajax Papers: Part III
read more
Difference between our two AJAX books
read more
Using webservice calls with multiple parameters
read more
Extending the IIS Configuration System using COM
read more
Mash-it Up with ASP.NET AJAX: Using a proxy to access remote APIs
read more
Working out with Amazon S3
read more
|
|
Please login to rate or to leave a comment.