Click to Rate and Give Feedback
Related Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
More ...
Articles by this Author
Fritz Onion demonstrates how the ListView control in ASP.NET 3.5 makes data-binding tasks easier with support for styling with CSS, flexible pagination, and a full complement of sorting, inserting, deleting, and updating features.

By Fritz Onion (March 2008)
To implement Silverlight in ASP.NET pages, you can encapsulate your Silverlight elements in ASP.NET controls. Here's how.

By Fritz Onion (January 2008)
The Web Service Software Factory is designed to provide guidance and enhanced tools for building Web services using ASMX or WCF.

By Fritz Onion (August 2007)
ASP.NET 2.0 development is the easiest ASP development yet. Fritz Onion reveals why.

By Fritz Onion (April 2007)
Control adapters let you provide alternate renderings of controls for mobile devices. But they can also be used to completely change the rendering of a con¬trol based on browser type, which can be useful in a number of situations.

By Fritz Onion (October 2006)
Building a customizable Web site complete with a collection of pluggable Web Parts is fairly easy with the portal infrastructure of ASP. NET 2. 0. This model is very flexible, allowing users to easily place your Web Parts anywhere on the Web page so they are free to customize your site.

By Fritz Onion (July 2006)
State management in Web applications is a contentious issue. Should you store user data per session or should you persist it across sessions? You can easily store information temporarily while someone navigates your site by using session state.

By Fritz Onion (April 2006)
As I write this column, the release candidates of the Microsoft® .NET Framework 2.0 and Visual Studio® 2005 have just come out, and by the time you read this, they will both already be on the shelves. It feels like it's been a long time coming.

By Fritz Onion (January 2006)
More ...
Popular Articles
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Joel Pobar presents an introduction to how compilers work and how you can write your own compiler to target the .NET Framework.

By Joel Pobar (February 2008)
In this article, author John Torjo presents a guide to his C++ GUI library called eGUI++ and explains how it makes user interface programming easier.

By John Torjo (June 2008)
Here the author uses Document Information Panels in the Microsoft 2007 Office system to manipulate metadata from Office docs for better discovery and management.

By Ashish Ghoda (April 2008)
More ...
Read the Blog
There are many things called threat modeling. Rather than argue about which is "the one true way," a good practice is to consider your needs and what your skills, abilities, and schedules are, and then work with a method that's best for you. In the July 2008 issue of MSDN Magazine, ...
Read more!
Want to develop games for Xbox Live? Want to get paid for it, too? Click on over to the XNA Team Blog to learn more about their initial rollout of the XNA Creators Club for XNA Game Studio. ...
Read more!
The Microsoft Entity Data Model (EDM), based on Dr. Peter Chen's Entity Relationship (ER) model, is the driving force behind the ADO.NET Entity Framework. The EDM is also the feature that most significantly differentiates the Entity Framework from other ORM-style technologies in the marketplace. In the July 2008 issue of MSDN ...
Read more!
System.IO.File is a handy helper class for reading and writing data, but its methods support only synchronous operation. Is there an easy way to provide File’s functionality for asynchronous file I/O? In the July 2008 issue of MSDN Magazine, Stephen Toub walks through several ...
Read more!
Remember .NET Terrarium, the interactive game meant to introduce .NET development techniques? Well, the Windows SDK team has released the source code for .NET Terrarium 2.0 on CodePlex. You can read more about this release on the Windows SDK blog and at Microsoft ...
Read more!
The Enumerable class plays an important role in every LINQ query you create. Because the Enumerable class's extension methods can process many other classes—including Array and List—you can use methods of the Enumerable class not only to create LINQ queries, but also to manipulate the behavior of arrays and other data structures. In the July 2008 issue of MSDN ...
Read more!
More ...
Extreme ASP.NET
Client-Side Web Service Calls with AJAX Extensions
Fritz Onion

Code download available at: ExtremeASPNET2007_01.exe (160 KB)
Browse the Code Online
Since its inception, ASP.NET has fundamentally been a server-side technology. There were certainly places where ASP.NET would generate client-side JavaScript, most notably in the validation controls and more recently with the Web Part infrastructure, but it was rarely more than a simple translation of server-side properties into client-side behavior-you as the developer didn't have to think about interacting with the client until you received the next POST request. Developers needing to build more interactive pages with client-side JavaScript and DHTML were left to do it on their own, with some help from the ASP.NET 2.0 script callbacks feature. This has changed completely in the last year.
At the Microsoft Professional Developer's Conference in September 2005, Microsoft unveiled a new add-on to ASP.NET, code-named "Atlas," which was focused entirely on leveraging client-side JavaScript, DHTML, and the XMLHttpRequest object. The goal was to aid developers in creating more interactive AJAX-enabled Web applications. This framework, which has since been renamed with the official titles of Microsoft® AJAX Library and the ASP.NET 2.0 AJAX Extensions, provides a number of compelling features ranging from client-side data binding to DHTML animations and behaviors to sophisticated interception of client POST backs using an UpdatePanel. Underlying many of these features is the ability to retrieve data from the server asynchronously in a form that is easy to parse and interact with from client-side JavaScript calls. The topic for this month's column is this new and incredibly useful ability to call server-side Web services from client-side JavaScript in an ASP.NET 2.0 AJAX Extensions-enabled page.

Calling Web Services with AJAX
If you have ever consumed a Web service in the Microsoft .NET Framework, either by creating a proxy using the wsel.exe utility or by using the Add Web Reference feature of Visual Studio®, you are accustomed to working with .NET types to call Web services. In fact, invoking a Web service method through a .NET proxy is exactly like calling methods on any other class. The proxy takes care of preparing the XML based on the parameters you pass, and it carefully translates the XML response it receives into the .NET type specified by the proxy method. The ease with which developers can use the .NET Framework to consume Web service endpoints is incredibly enabling, and is one of the pillars that make service-oriented applications feasible today.
The ASP.NET 2.0 AJAX Extensions enable this exact same experience of seamless proxy generation for Web services for client-side JavaScript that will run in the browser. You can author an .asmx file hosted on your server and make calls to methods on that service through a client-side JavaScript class. For example, Figure 1 shows a simple .asmx service that implements a faux stock quote retrieval (with random data).
In addition to the standard .asmx Web service attributes, this service is adorned with the ScriptService attribute that makes it available to JavaScript clients as well. If this .asmx file is deployed in an ASP.NET AJAX-Enabled Web application, you can invoke methods of the service from JavaScript by adding a ServiceReference to the ScriptManager control in your .aspx file (this control is added automatically to your default.aspx page when you create a Web site in Visual Studio using the ASP.NET AJAX-enabled Web site template):
<asp:ScriptManager ID="_scriptManager" runat="server">
  <Services>
    <asp:ServiceReference Path="StockQuoteService.asmx" />
  </Services>
</asp:ScriptManager>
Now from any client-side JavaScript routine, you can use the MsdnMagazine.StockQuoteService class to call any methods on the service. Because the underlying mechanism for invocation is intrinsically asynchronous, there are no synchronous methods available. Instead, each proxy method takes one extra parameter (beyond the standard input parameters)- a reference to another client-side JavaScript function that will be called asynchronously when the method completes. The example page shown in Figure 2 uses client-side JavaScript to print the result of calling the stock quote Web service to a label (span) on the page.
If something goes wrong with a client-side Web service call, you definitely want to let the client know, so it's usually wise to pass in another method that can be invoked if an error, abort, or timeout occurs. For example, you might change the OnLookup method shown previously as follows, and add an additional OnError method to display any problems:
function OnLookup()
{           
  var stb = document.getElementById("_symbolTextBox");  
  MsdnMagazine.StockQuoteService.GetStockQuote(
    stb.value, OnLookupComplete, OnError);
}
    
function OnError(result)
{
  alert("Error: " + result.get_message());
}
This way if the Web service call fails, you will notify the client with an alert box. You can also include a userContext parameter with any Web service calls made from the client, which is an arbitrary string passed in as the last parameter to the Web method, and it will be propagated to both the success and failure methods as an additional parameter. In this case, it might make sense to pass the actual symbol of the stock requested as the userContext so you can display it in the OnLookupComplete method:
function OnLookup()
{           
  var stb = document.getElementById("_symbolTextBox");  
  MsdnMagazine.StockQuoteService.GetStockQuote(
    stb.value, OnLookupComplete, OnError, stb.value);
}

function OnLookupComplete(result, userContext)
{
  // userContext contains symbol passed into method
  var res = document.getElementById("_resultLabel");
  res.innerHTML = userContext + " : <b>" + result + "</b>";
}
If you find that you're making many different calls to a Web service, and that you re-use the same error and/or complete methods for each call, you can also set the default error and succeeded callback method globally. This avoids having to specify the pair of callback methods each time you make a call (although you can choose to override the globally defined methods on a per-method basis). Here is a sample of the OnLookup method that sets the default succeeded and failed callback methods globally instead of on a per-call basis.
// Set default callbacks for stock quote service
MsdnMagazine.StockQuoteService.set_defaultSucceededCallback(
                 OnLookupComplete);
MsdnMagazine.StockQuoteService.set_defaultFailedCallback(
                 OnError);
function OnLookup()
{           
  MsdnMagazine.StockQuoteService.GetStockQuote(stb.value);
}
Another interesting alternative to building a complete .asmx file for your Web service methods is to embed the Web service methods directly in the page class. If it doesn't make sense to build a complete Web service endpoint for the methods you want to call, you can expose a Web method from your page that is callable from client-side JavaScript by adding a server-side method to your page (either directly in the page or in the codebehind) and annotating it with the WebMethod attribute. You will then be able to invoke it via the client-side object PageMethods. The example in Figure 3 shows the stock quote service sample rewritten to be entirely contained in a single page instead of split into a separate Web service.
Bear in mind that these client-side proxies can only be generated from ASP.NET .asmx endpoints, Windows Communication Foundation .svc endpoints, or WebMethods embedded directly in a page, and are not a general mechanism for calling arbitrary Web services. In fact, there is a general restriction on the underlying XmlHTTPRequest object that requests be restricted to the same domain from which the page was loaded (for security reasons), so this technique could not be used to call arbitrary Web services regardless of whether the client-side proxies supported it. If you do find the need to call external Web services, your best bet is to set up a bridge .asmx endpoint in your own application that calls into a .NET proxy class (generated with wsdl.exe or Add Web Reference in Visual Studio) for the external Web service.

How It Works
It might seem surprising at first that you can take a standard .asmx Web service and access it from client-side JavaScript within a browser with almost no changes. The secret lies in the registration of a new .asmx HTTP handler, added to the configuration file of every ASP.NET AJAX-enabled Web site:
<httpHandlers>
  <remove verb="*" path="*.asmx"/>
  <add verb="*" path="*.asmx" 
       type="Microsoft.Web.Services.ScriptHandlerFactory" 
       validate="false"/>
</httpHandlers>
This newly registered handler will invoke the standard Web service handler (System.Web.Services.Protocols.WebServiceHandlerFactory) if it is a standard Web service request made to an .asmx endpoint. If, however, the request has a trailing /js in the URL or contains a query string with an mn= variable (such as ?mn=GetStockQuote), the handler will either return a chunk of JavaScript that creates a client-side proxy for the Web service (the /js option), or it will invoke the corresponding method defined in the WebService-derived class and package up the response in a JavaScript Object Notation (JSON)-encoded string (the ?mn= option).
When a page includes a client-side reference to an .asmx service (via the ServiceReference element within the ScriptManager control), it injects a script element that references the .asmx file with a trailing /js, creating a proxy in the client. For example, the stock quote page I built earlier rendered with the following script element in it:
<script src="StockQuoteService.asmx/js" 
        type="text/javascript"></script>
This is, of course, in addition to the script references added for the Microsoft AJAX Libraries, which include the client-side features needed to interact with this proxy. If you try navigating to this endpoint yourself, you will see the following JavaScript (elided):
Type.registerNamespace('MsdnMagazine');
MsdnMagazine.StockQuoteService=function() {
  this._timeout = 0;
  this._userContext = null;
  this._succeeded = null;
  this._failed = null;
}
MsdnMagazine.StockQuoteService.prototype={
GetStockQuote:Sys.Net._WebMethod._createProxyMethod(this,
     "GetStockQuote", 
     "MsdnMagazine.StockQuoteService.GetStockQuote",
     "symbol"), ...
}
This JavaScript is using features of the Microsoft AJAX Libraries (like namespaces and the WebMethod class) that are included with every page that includes a ScriptManager control. The proxy method created by this JavaScript is initialized to invoke the .asmx endpoint with the query string ?mn=GetStockQuote in this case, so that whenever you call MsdnMagazine.StockQuoteService.GetStockQuote from the client, it turns into an asynchronous Web request for the same .asmx endpoint. This combination of client-side proxy generation and server-side support for JavaScript-initiated Web service calls means you can include client-side calls to your .asmx Web services in an intuitive way.

Serialization
The default serialization of AJAX-based Web services is JSON. If you look at a trace of the page shown in the last section in action, the bodies of the Web service request and response look like this:
Request: {"symbol":"ABC"}
Response: 51
This is definitely not the standard XML format you are probably accustomed to seeing when calling your .asmx Web services. Since .asmx endpoints were built to serialize into XML, one of the major additions of the ASP.NET 2.0 AJAX Extensions is a JSON serializer. There are actually two of them-one implemented in JavaScript for use on the client, and one implemented in .NET for use on the server, specifically when an AJAX client invokes an .asmx endpoint. The server-side serializer is available through the Microsoft.Web.Script.Serialization.JavaScriptSerializer class and the client-side serializer is available through Sys.Serialization.JavaScriptSerializer. One of the major advantages of using JSON as a serialization format over XML is that you can deserialize objects in JavaScript by simply evaluating a JSON string. The deserialize method of the client serializer class ends up being very short (error checking removed):
Sys.Serialization.JavaScriptSerializer.deserialize=
    function(){eval('('+data+')');}
The serialize method of the JavaScriptSerializer, on the other hand, is considerably more involved. Another advantage to using JSON is its relatively compact representation compared with the XML equivalent.
Much as the XmlSerializer used by standard Web services serializes types to XML, you can take almost any .NET type and serialize it into JSON with JavaScriptSerializer. If you want to try it yourself, it's just a matter of calling the Serialize method of the JavaScriptSerializer class. Figure 4 shows a sample console application that serializes the complex Person type (shown in Figure 5), as an example. (It must include an assembly reference to the Microsoft.Web.Extensions.dll installed in the Global Assembly Cache (GAC) with the ASP.NET AJAX Extensions.)
The output of the console application would be the Person class in JSON format, or:
{"Married":true,"Age":33,"FirstName":"Bob","LastName":"Smith"}
Like XmlSerializer, JavaScriptSerializer will only serialize publicly accessible data in a type, and there is no support for resolving cyclic references. But any types that can be serialized by a standard .asmx Web service will work fine with this serializer (and yes, this includes DataSet). With this knowledge in place, you can build a more complex Web service, knowing that it will handle complex types as easily as any SOAP-based Web service defined in an .asmx file.
The example in Figure 6 shows a Web service called MarriageService that implements a Marry method to take two Person objects (as defined earlier) and modify their attributes appropriately. (The accompanying ASP.NET page is included with the code download for this issue.)
If you'd rather work with XML in your client-side script, that option is available as well. In addition to the standard WebMethod attribute used when defining Web services, there is a new attribute in the Microsoft.Web.Script.Services namespace called ScriptMethod, which has a ResponseFormat property that can be set to either Json or Xml (it defaults to Json).
namespace PS
{
    [ScriptService] 
    [WebService(Namespace = "http://pluralsight.com/ws")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class StockQuoteService : WebService
    {
        [WebMethod]
        public int GetStockQuote(string symbol)
        {
            return (new Random()).Next(0, 120);
        }
    }
}
The serialized response would then be:
<?xml version="1.0" encoding="utf-8"?><int>74</int>
It is up to you when you invoke this method from client-side JavaScript to handle the XML response. If you plan on running a transformation on it or are already using MSXML, this may be useful.

Conclusion
It's worth pointing out that the ASP.NET 2.0 AJAX Extensions provide two pre-built services to tap into specific ASP.NET 2.0 application services from client-side code: ProfileService and AuthenicationService. With these two client-side proxy classes you can set and retrieve profile values for individual clients, as well as perform authentication (via the default Membership provider) and grant authentication cookies completely within client script.
While many discussions and demonstrations of the ASP.NET 2.0 AJAX Extensions focus on the flashy controls that enable responsive user interfaces, one of the most impressive and useful features is the ability to call Web services directly from client-side JavaScript. With a full .NET Framework/JSON serializer, direct integration with the familiar .asmx Web services, support for batching, and auto-generated bridges to external Web services, the breadth and depth of support for Web services makes this perhaps the most compelling feature of all.

Send your questions and comments for Fritz to  xtrmasp@microsoft.com..


Fritz Onion is a cofounder of Pluralsight, a Microsoft .NET training provider, where he heads the Web development curriculum. Fritz is the author of Essential ASP.NET (Addison Wesley, 2003) and Essential ASP.NET 2.0 (Addison Wesley, 2006). Reach him at pluralsight.com/fritz.

Page view tracker