Registering functions in another class
In the above example, our server-side functions resided within the code behind of the executing page. However, there’s no reason why these functions can’t be in a separate class file. Remember, the way the wrapper works is to find all methods within the specified class that have the Ajax.AjaxMethod
. The class in question is specified via the second script tag. Using Ajax.Utility.RegisterTypeForAjax
we can specify any class we want. For example, it would be reasonable to keep our server-side functions in a separate class:
Public Class AjaxFunctions
<Ajax.AjaxMethod()> _
Public Function Validate(username As String, password As String) As Boolean
'do something
'Return something
End Function
End Class
We could have the Ajax wrapper create proxies for this class by specifying this class’s type instead of the pages:
VB.NET
Private Sub Page_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Ajax.Utility.RegisterTypeForAjax(GetType(AjaxFunctions))
'...
End Sub
C#
private void Page_Load(object sender, EventArgs e){
Ajax.Utility.RegisterTypeForAjax(typeof(AjaxFunctions));
//...
}
Remember, the client-side proxy takes the name of <ClassName>.<ServerSideFunctionName>
. Therefore, if our ServerSideAdd
function was located in the fictional AjaxFunctions class above, our client-side call would be: AjaxFunctions.ServerSideAdd(1,2)
How the proxy really works
The second script tag generated by the Ajax utility (or manually inserted by you) passes the namespace, class name and assembly of the page. Armed with this information, the Ajax.PageHandlerFactory
is able to use reflection and get the details about any functions which have a certain attribute. Obviously, the handler looks for functions with the AjaxMethod
attribute, gets their signature (return type, name, and parameters) and is thus able to create the necessary client-side proxy. Specifically, the wrapper creates a JavaScript object named the same name as your class which exposes the proxy. In other words, given a server-side class AjaxFunctions with an Ajax method ServerSideAdd
, we should expect a JavaScript object named AjaxFunction
which exposes a ServerSideAdd
function. You can see this in action by pointing your browser to the path of the second script tag.
Returning Unicode characters
Ajax .NET wrapper is able to return Unicode characters from the server to the client. To do so, values must be html encoded on the server before being returned. For example:
[Ajax.AjaxMethod]
public string Test1(string name, string email, string comment){
string html = "";
html += "Hello " + name + "<br>";
html += "Thank you for your comment <b>";
html += System.Web.HttpUtility.HtmlEncode(comment);
html += "</b>.";
return html;
}
SessionState
It’s likely that you’ll need to access session information in your server side function. To do so, you must simply tell Ajax to enable such functionality via a parameter passed to the Ajax.AjaxMethod
attribute.
While looking at the session capabilities of the wrapper, let’s look at a couple other features. In this example, we have a document management system which puts a lock on a document while a user is editing it. Other users can request to be notified when the document because available. Without AJAX, we’d need to wait until the user posted back in order to check if his or her queued documents were available. This is obviously not ideal. Using Ajax with session state support, this is quite easy.
First we’ll write our server side function, the goal of which is to loop through the documentIds the user wishes to edit (stored in a session) and return all released documents.
VB.NET
<Ajax.AjaxMethod(HttpSessionStateRequirement.Read)> _
Public Function DocumentReleased() As ArrayList
If HttpContext.Current.Session("DocumentsWaiting") Is Nothing Then
Return Nothing
End If
Dim readyDocuments As New ArrayList
Dim documents() As Integer = CType(HttpContext.Current.Session("DocumentsWaiting"), Integer())
For i As Integer = 0 To documents.Length - 1
Dim document As Document = document.GetDocumentById(documents(i))
If Not document Is Nothing AndAlso document.Status = DocumentStatus.Ready Then
readyDocuments.Add(document)
End If
Next
Return readyDocuments
End Function
C#
[Ajax.AjaxMethod(HttpSessionStateRequirement.Read)]
public ArrayList DocumentReleased(){
if (HttpContext.Current.Session["DocumentsWaiting"] == null){
return null;
}
ArrayList readyDocuments = new ArrayList();
int[] documents = (int[])HttpContext.Current.Session["DocumentsWaiting"];
for (int i = 0; i < documents.Length; ++i){
Document document = Document.GetDocumentById(documents[i]);
if (document != null && document.Status == DocumentStatus.Ready){
readyDocuments.Add(document);
}
}
return readyDocuments;
}
}
Notice that we specify the HttpSessionStateRequirement.Read
value (alternatives being Write
and ReadWrite
).
Now we write our JavaScript to take advantage of this method:
<script language="javascript">
function DocumentsReady_CallBack(response){
if (response.error != null){
alert(response.error);
return;
}
if (response.value != null && response.value.length > 0){
var div = document.getElementById("status");
div.innerHTML = "The following documents are ready!<br />";
for (var i = 0; i < response.value.length; ++i){
div.innerHTML += "<a href=\"edit.aspx?documentId=" + response.value[i].DocumentId + "\">" + response.value[i].Name + "</a><br />";
}
}
setTimeout('page.DocumentReleased(DocumentsReady_CallBack)', 10000);
}
</script>
<body onload="setTimeout('Document.DocumentReleased(DocumentsReady_CallBack)', 10000);">
Our server side function is called once on page load and subsequently every 10 seconds. The call back function checks the response to see if any values were returned, and if so displays the newly available documents to the user in a div tag.
Conclusion
AJAX technology has already lead to sleek and rich web interfaces, previously reserved for desktop development. The Ajax .NET wrapper allows you to easily take advantage of this new power. Note that both the Ajax .NET wrapper and the documentation are under development.
Comments