Ajax.NET is designed to allow remote calling of classes written in a .NET language, specifically those accessed through ASP.NET. The .NET Framework has been around since 1999, and one of its aims is to enable code written in different languages to integrate with each other seamlessly. The main .NET languages are Visual Basic .NET and C#, but there are also many others, ranging from J#, a .NET port of Java, to COBOL .NET.
As with the other frameworks discussed in this chapter, Ajax.NET uses a cross-browser, client-side library to post function calls to the server via the platform-specific version of XmlHttpRequest. It also uses reflection to analyze the server-side code in the ASP.NET page. Unlike the other frameworks, however, Ajax.NET takes advantage of a .NET feature called attributes, which is used to mark the methods that will be available from the client.
To use Ajax.NET, you need to be running IIS version 5 or greater and have the .NET Framework installed. Although creating web sites that use ASP.NET can be done easily via Visual Studio .NET, this is not essential and can be done using a standard editor.
Note |
Chapter 6 discusses how to set up a new virtual folder for IIS and create an ASP.NET web project. |
Download the Ajax DLL from http://ajax.schwarz-interactive.de/. At the time of this writing, two releases are available: any one with a version number of 5.7.25.1 or greater is for use with version 2 of .NET; if you are not running this, download one of the earlier DLLs, such as 5.7.22.2.
Next, you need to add a reference to this DLL to each project in which you use Ajax.NET.
You need to create your project before setting up Ajax.NET, so start Visual Studio .NET and add a new ASP.NET web application named AjaxTest.
Note |
The project can be in C#, Visual Basic .NET, or any other option available on your machine. |
Right-click the project name, AjaxTest, and then choose AddNew Folder. Name the new folder ref. Add the Ajax.dll downloaded earlier to this folder, and then add a reference to it by right-clicking the References folder, browsing to ref, and double-clicking Ajax.dll. Finally, rename the WebForm1.aspx page as Index.aspx. The layout of the project in the Solution Explorer on the right-hand side of Visual Studio will now look similar to Figure 10-7.
You also need to modify the project's web configuration file. Open Web.config and add a new <httpHandlers> element underneath <system.web>.
<configuration> <system.web> <httpHandlers> <add verb="POST,GET" path="ajax/*.ashx" type="Ajax.PageHandlerFactory, Ajax" /> </httpHandlers>
This tells IIS that any POST or GET request that is directed to ajax/*.ashx, where * means any, should be serviced by the Ajax.PageHandlerFactory instead of the built-in one that handles all other requests.
An HttpHandler handles a client request, either a GET request as a simple URL or a more complicated POST request containing additional data from an HTML form. It is responsible for any action taken, such as specialized business logic that must be followed. The built-in handler deals with .aspx, .asmx, and other similar ASP.NET files. Ajax.PageHandlerFactory processes requests with Ajax in the path and uses the information in the URL to generate the necessary client-side JavaScript based on the business object specified.
The initial setup is now complete and it's time to build the web page that will take advantage of Ajax.NET.
To make sure that Ajax.NET has been installed and registered correctly, a simple test of the system is made using the Index.aspx file.
From the Solution Explorer in Visual Studio .NET, right-click Index.aspx and choose View Code. Add the following line to the Page_Load procedure:
public class Index : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
Ajax.Utility.RegisterTypeForAjax(typeof(Index));
}
The purpose of this line is to inject into the resulting HTML the necessary JavaScript files.
You are now in a position to test the set up. Start the project by pressing F5 and you should be greeted with a blank page. On viewing the source, you will notice the following two <script> elements:
<script type="text/javascript" src="/AjaxTest/ajax/common.ashx"></script> <script type="text/javascript" src="/AjaxTest/ajax/AjaxTest.Index,AjaxTest.ashx"></script>
The first script provides the XmlHttpRequest functionality; the second is specific to the page and contains a few helper functions along with any server-side methods that have been made available.
To make a method available from the client, first add it to Index.aspx within the definition of the Index class:
public class Index : System.Web.UI.Page { public int Add(int firstNumber, int secondNumber) { return firstNumber + secondNumber; }
To inform the Ajax.NET handler that this method needs a client-side JavaScript implementation, it is decorated with a .NET attribute:
[Ajax.AjaxMethod()] public int Add(int firstNumber, int secondNumber) { return firstNumber + secondNumber; }
Access is then available client-side using the syntax PageClass.Method(Arg1, Arg2, . . .). So, in this case the code would be:
var response = Index.Add(6, 8); alert(response.value);
The response returned by Index.Add has three properties: value (as seen above), error, and request. To make your code more robust, you should check the error property to see if it is true before proceeding:
var response = Index.Add(6, 8); if (response.error) { alert(response.error); } else { alert(response.value); }
The request property provides access to the underlying XmlHttpRequest object and in more complicated scenarios can be helpful while debugging as the raw XML can be accessed.
The preceding example shows a synchronous call where, after the call to Index.Add(), the script waited while the method was being processed on the server. To start an asynchronous call, whereby the script continues after the method call, pass a function pointer as the last argument of the method:
var callback = function (response) { if (response.error) { alert(response.error); } else { alert(response.value); } } Index.Add(6, 8, callback);
When using the asynchronous call, you can also pass in a context parameter immediately after the callback function. This is returned in the response.context property and enables you to use the same callback procedure for multiple calls while differentiating on return which each applied to:
var callback = function (response) { if (response.error) { alert(response.error); } else { alert(response.context + response.value); } } Index.Add(6, 8, callback, "6 + 8 = "); Index.Add(9, 2, callback, "9 + 2 = ");
The preceding code would display the original sum as well as the result in two separate alert boxes.
Unlike the other two projects demonstrating JPSpan and DWR, there is only one page used with Ajax.NET: Customer-AjaxNET.aspx.
From the Solution Explorer in Visual Studio .NET, add a new web form to the project called Customer-AjaxNET.aspx. Before you make any further modifications to this page, the business class needs to be created; otherwise, Visual Studio .NET will complain that you are referencing an object that doesn't exist.
In addition to accessing methods directly embedded in an .aspx page, you can make accessible the methods of any external class, provided that the types returned can be converted to a JavaScript format. Instead of using the current page class in the Ajax.Utility.RegisterTypeForAjax method, you need to pass the custom class.
Add a new class to the AjaxTest project and save it as Customer.cs. This implements the same functionality as in the other examples in this chapter—namely a single method, GetAddressFromEmail().
Note |
As before, the following class is intended to aid the demonstration of using Ajax; it is certainly not a model of how to write a business class. |
The class begins with a number of using statements to provide easier access to the needed types:
using System; using System.Collections; using System.Data.OleDb; using System.Text;
The System namespace contains all the basic functionality and primitive data types, and System.Collections uses the Hashtable class that is used to store the address details. This is very similar to the hashmap from the DWR example. System.Data.OleDb contains classes to connect to and retrieve data from an OleDb datasource (SQL Server or Microsoft Access, for example). The System.Text class contains methods to manipulate strings and is needed for adding the extra quotation marks to the user-supplied e-mail address when necessary and also to provide access to the StringBuilder class used to construct the SQL statement.
Next comes the namespace and class declaration itself:
The GetAddressFromEmail() method is then implemented:
public Hashtable GetAddressFromEmail(string Email) { Hashtable address = new Hashtable(); address["success"] = false;
The return value is a hashtable, which stores data items that can be accessed through a unique key in a similar way to the hashmap used in the DWR example. A key named success is assigned a value of false, which will be modified to true if the call to the database is successful.
The next step is to create a connection to the Sales database. As mentioned earlier, the connection details for the database would be stored in a configuration file:
string sConnString = "Provider=SQLOLEDB; Data Source='localhost'; " + "Initial Catalog='sales'; User Id='Test'; Password='test';"; OleDbConnection conn = new OleDbConnection(sConnString); conn.Open();