Section 16.2. Ajax.NET


16.2. Ajax.NET

Michael Schwarz, a German MVP for ASP and ASP.NET, published his free Ajax.NET library some time ago. It offers Ajax functionality (data exchange 316ith the server, including serialization of many data types), client callbacks, and some advanced features. The source code for Ajax.NET was eventually released to the public (see http://weblogs.asp.net/mschwarz/archive/2005/08/11/422293.aspx) and development on the library stopped. However, the code has since been moved into the BorgWorX project (see http://www.borgworx.net). Schwarz went on to work on Ajax.NET Professional (http://www.ajaxpro.info), which is available under a closed-source license, but is still free. Ajax.NET and Ajax.NET Professional can both be used with ASP.NET 1.1 and 2.0.

Migrating to Ajax.NET Professional

Using Ajax.NET Professional is quite similar to Ajax.NET, since most of the interfaces have not changed. One difference is the installation. Ajax.NET Professional supports both ASP.NET 1.1 and 2.0, but all in one package. Therefore, the distribution archive contains two assemblies:

  • AjaxPro.dll for ASP.NET 1.1

  • AjaxPro.2.dll for ASP.NET 2.0

Apart from that, using the library is quite similar. Again, you have to add elements to your Web.config, but this time the virtual filename changes, as does the type. For ASP.NET 1.1, you use this directive:

 <configuration>   <system.web>     <httpHandlers>       <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.Ajax HandlerFactory, AjaxPro" />     </httpHandlers>   </system.web> </configuration> 

For ASP.NET 2.0, the <add> element changes as follows:

 <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro.2" /> 

The other changes are similar. All occurrences of the Ajax class change to AjaxPro, obviously. Also, most notably, you have to omit the parentheses in [AjaxPro.AjaxMethod].

The associated discussion group for Ajax.NET Professional resides at http://groups.google.com/group/ajaxpro. There, the library's author also announces new releases or beta versions. More information about Ajax.NET Professional is available at http://weblogs.asp.net/mschwarz.


This section focuses primarily on the original Ajax.NET release but also briefly describes how to migrate an application to Ajax.NET Professional. This discussion is not meant to provide an exhaustive guide to these libraries, but just as a teaser, showing the basic functionality and one or two advanced features to whet your appetite.

16.2.1. Using Ajax.NET

To use Ajax.NET, download the Ajax.dll library from the Ajax.NET web site (http://ajax.schwarz-interactive.de). Recently, this URL redirects to another site, but the .dll file used in this example is still available from http://ajax.schwarz-interactive.de/download/ajax.zip.

In Visual Studio, start a new web site (the Ajax.NET settings would collide with the Atlas settings in the Web.config file) and add a reference to Ajax.dll, or just copy the Ajax.dll assembly to the application's Bin directory. Doing so provides you with IntelliSense support for the library, as Figure 16-2 shows.

Figure 16-2. Ajax.NET integrates into Visual Studio and provides IntelliSense


Create a new ASP.NET page and import the Ajax namespace that is provided by Ajax.NET. Important: the current page must have an (arbitrary) class name:

 <%@ Page Language="C#" ClassName="AjaxNETExample" %> <%@ Import Namespace="Ajax" %> 

Then, in the Page_Load() method, register the current page with Ajax.NET. That's what you need the class name foryou have to provide its type to the RegisterTypeForAjax() method, like this:

 protected void Page_Load(object sender, EventArgs e) {   Ajax.Utility.RegisterTypeForAjax(this.GetType()); } 

From this point, using the Ajax.NET library is easy and intuitive. On the server side, you implement the "business logic"for our example, we will once again square a number. Ajax.NET provides a set of attributes you can use to identify Ajax.NET-enabled portions of your code. The [Ajax.AjaxMethod()] attribute makes any method accessible through JavaScript. The following code creates a server-side function called squareNumber(); the Ajax.AjaxMethod() attribute will cause the library to create a JavaScript proxy for the method.

 [Ajax.AjaxMethod()] public int squareNumber(int a) {   return Convert.ToInt32(Math.Pow(a, 2)); } 

And this is all that is required in server-side code! The rest is JavaScript.

An HTML form contains a text field that expects a number to be squared as a parameter and calls a client-side function in response. In our example, this function will be called callComplete(). (This name does not exactly convey the purpose of this function, but it's a name we have used all over this book, so it is recycled here.) Here is the page markup, showing the call to the callComplete() method:

 <form  runat="server">   <div>     <nobr>       <input type="text"  name="a" size="2" />       <sup>2</sup> =       <span  style="width: 50px;" ></span>     </nobr>     <br />     <input type="button" value="Square Number"            onclick="callComplete(this.form)" />   </div> </form> 

The callComplete() function itself calls the server squareNumber function by using a client proxy. The proxy is generated automatically by Ajax.NET. In the example, the proxy can be accessed using AjaxNETExample.squareNumber(). Here is the code for the callComplete() function:

 <script language="JavaScript" type="text/javascript"> function callComplete(f) {   var result = AjaxNETExample.squareNumber(     parseInt(f.elements["a"].value));   document.getElementById("aSquare").innerHTML =     result.value; } </script> 

The result returned from the server-side function has three properties:


error

The error message, if any


request

A reference to the XMLHttpRequest object used for the call (allowing the user to retrieve additional information about the HTTP request and response)


value

The returned value

In the example, we use only the value property, but a real-world application obviously requires an extra layer of error handling and should test the error property as a minimum.

One more step is required. The call to the RegisterTypeForAjax() method places elements similar to these into the page markup:

 <script type="text/javascript" src="/books/3/491/1/html/2//AjaxNET/ajax/common.ashx"></script><script type="text/javascript" src="/books/3/491/1/html/2//AjaxNET/ajax/ASP.AjaxNETExample,App_Web_duood5sl .ashx"></script> 

(This assumes that the current web application is called AjaxNET.) But the files referenced in the src attributes do not exist yetAjax.NET consists only of the Ajax.dll assembly. The ajax subdirectory does not exist, either.

To make all of this work (that is, to virtualize the files and folders referenced in the markup), you must place the following directive in the Web.config file as a child of the <system.web> section:

 <httpHandlers>   <add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax" /> </httpHandlers> 

This enables Ajax.NET to parse the current page, look for all methods with the Ajax.AjaxMethod() attribute, and create the JavaScript proxy objects, making the whole application work. Example 16-3 shows you the complete code, which as you can see is quite compact

Remember that you must register the Ajax.NET handler in the Web.config file before you run this example.


Example 16-3. Using Ajax.NET

 AjaxNET.aspx <%@ Page Language="C#" ClassName="AjaxNETExample" %> <%@ Import Namespace="Ajax" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">   protected void Page_Load(object sender, EventArgs e)   {     Ajax.Utility.RegisterTypeForAjax(this.GetType());   }   [Ajax.AjaxMethod()]   public int squareNumber(int a)   {     return Convert.ToInt32(Math.Pow(a, 2));   } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">   <title>Ajax</title>   <script language="JavaScript" type="text/javascript">   function callComplete(f) {     var result = AjaxNETExample.squareNumber(       parseInt(f.elements["a"].value));     document.getElementById("aSquare").innerHTML =       result.value;   }   </script> </head> <body>   <form  runat="server">     <div>       <nobr>         <input type="text"  name="a" size="2" />         <sup>2</sup> =         <span  style="width: 50px;"></span>       </nobr>       <br />       <input type="button" value="Square Number"              onclick="callComplete(this.form)" />     </div>   </form> </body> </html> 

Figure 16-3 shows the results of loading Example 16-3, entering a number, and clicking the Square Number button.

Figure 16-3. Squaring numbers with Ajax.NET


You might have noticed that this is a synchronous communication, even though the current Ajax implementations typically use an asynchronous call. But it is trivial to extend the example so that an asynchronous callback function is used. To do so, you just provide an extra parameter to the server function you call using JavaScriptnamely, a reference to the callback function. Then, this callback function automatically gets the result. Example 16-4 shows the complete markup and script for the preceding example, this time using asynchronous communication, with changes highlighted in the code.

Example 16-4. Using Ajax.NET with asynchronous communication

 AjaxNETAsync.aspx <%@ Page Language="C#" ClassName="AjaxNETExample" %> <%@ Import Namespace="Ajax" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">   protected void Page_Load(object sender, EventArgs e)   {     Ajax.Utility.RegisterTypeForAjax(typeof(AjaxNETExample));   }   [Ajax.AjaxMethod()]   public int squareNumber(int a)   {     return Convert.ToInt32(Math.Pow(a, 2));   } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server">   <title>Ajax</title>   <script language="JavaScript" type="text/javascript">   function squareNumber(f) {     AjaxNETExample.squareNumber(       parseInt(f.elements["a"].value),       callComplete);   }     function callComplete(result) {     document.getElementById("aSquare").innerHTML =       result.value;   }   </script> </head> <body>   <form  runat="server">     <div>       <nobr>         <input type="text"  name="a" size="2" />         <sup>2</sup> =         <span  style="width: 50px;" ></span>       </nobr>       <br />       <input type="button" value="Square Number"              onclick="squareNumber(this.form)" />     </div>   </form> </body> </html> 

Apart from exchanging scalar data types with the server, Ajax.NET also supports more complex data types, objects, even images. To give you a sense of what the library can do with more complex data, we will use a database query, return a dataset, and then access it on the client side to fill a list.

We start off by querying the database. Again, the Ajax.AjaxMethod() attribute ensures that the returned data will be available on the client side, as well:

 [Ajax.AjaxMethod()] public DataSet loadVendors() {   SqlConnection conn = new SqlConnection(     "server=(local)\\SQLEXPRESS; Integrated Security=true; Initial Catalog=AdventureWorks");   conn.Open();   SqlCommand comm = new SqlCommand(     "SELECT VendorID, Name FROM Purchasing.Vendor",     conn);   SqlDataAdapter adap = new SqlDataAdapter(comm);   DataSet ds = new DataSet();   adap.Fill(ds);   return ds; } 

Using client-side JavaScript, this method will be called later:

 function loadVendors() {   AjaxNETExample.loadVendors(callComplete); } 

To output the dataset, an HTML selection list (<select> element) is created. At first it's empty, but it will be filled later on.

 <select name="vendors"></select> 

An HTML button will trigger the whole process:

 <input type="button" value="Load Vendors"        onclick="loadVendors();" /> 

All that remains is the callback function, once again called callComplete(). The code in the callComplete() method loops through the dataset returned from the server. With each iteration, a new list option is generated in JavaScript code and added to the list. The syntax for creating a new list option is as follows:

 var op = new Option(<name>, <value>); 

The name of the option is the caption within the list, the value (which is not required) is the information that will be transferred to the server when the form is submitted via GET or POST.

Using this knowledge, you can write JavaScript like the following to populate the list with the dataset:

 function callComplete(result) {   var ds = result.value;   for (var i=0; i < ds.Tables[0].Rows.length; i++) {     var op = new Option(       ds.Tables[0].Rows[i].Name,       ds.Tables[0].Rows[i].VendorID);     document.forms[0].elements["vendors"].options[i] = op;   } } 

You can try to pretty up the code furtherfor instance, by making the button vanish after the list has been filled, or by using proper error handling when the dataset cannot be created. But for demonstration purposes, this example serves well. Example 16-5 shows the complete code.

Example 16-5. Using a dataset on the client side

 AjaxNETDataset.aspx <%@ Page Language="C#" ClassName="AjaxNETExample" %> <%@ Import Namespace="Ajax" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server">   protected void Page_Load(object sender, EventArgs e)   {     Ajax.Utility.RegisterTypeForAjax(this.GetType());   }   [Ajax.AjaxMethod()]   public DataSet loadVendors()   {     SqlConnection conn = new SqlConnection(       "server=(local)\\SQLEXPRESS; Integrated Security=true; Initial Catalog=AdventureWorks");     conn.Open();     SqlCommand comm = new SqlCommand(       "SELECT VendorID, Name FROM Purchasing.Vendor",       conn);     SqlDataAdapter adap = new SqlDataAdapter(comm);     DataSet ds = new DataSet();     adap.Fill(ds);     return ds;   } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head  runat="server">   <title>Ajax</title>   <script language="JavaScript" type="text/javascript">   function loadVendors() {     AjaxNETExample.loadVendors(callComplete);   }   function callComplete(result) {     var ds = result.value;     for (var i=0; i < ds.Tables[0].Rows.length; i++) {       var op = new Option(         ds.Tables[0].Rows[i].Name,         ds.Tables[0].Rows[i].VendorID);       document.forms[0].elements["vendors"].options[i] = op;     }   }   </script> </head> <body>   <form  runat="server">     <input type="button" value="Load Vendors"            onclick="loadVendors();" />     <select name="vendors"></select>   </form> </body> </html> 

Figure 16-4 shows the result of loading the page and pressing the Load Vendors button.

Figure 16-4. The data in the list comes dynamically from the server





Programming Atlas
Programming Atlas
ISBN: 0596526725
EAN: 2147483647
Year: 2006
Pages: 146

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net