Traditional Ajax With Asp .Net And Modern PageMethods Approach

Traditional Ajax Method With Asp.Net

Basicaly, we use XMLHttpRequest client side class to use ajax functionality. The use of bare XMLHttpRequest is a traditional way to accomplish asynchronous process.

This XMLHttpRequest class implementation is written in JScript or VbScript client script and usually it is being used by Asp Classic but Asp .Net can use it and so other open source code language.
To make an async process using XMLHttpRequest we can use client side development only.

Although the traditional way is not die and still a good option rather than not to use the asynx process but when we are using Asp .Net to do ajax it is recomended to use a modern approaches.
This modern approach is using Asp.Net Ajax Extension. It includes both server and client side development. I use PageMethods in this post to be specific. In fact, a lot of option of using Asp.Net Ajax.
However we need to know how to implement or code with XMLHttpRequest and so we can compare it with modern (Asp.Net Ajax) method.

XMLHttpRequest Example

I use Asp.Net file to show you how to use traditional ajax.

.aspx file:

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script language="javascript" type="text/javascript">
         
        function httprequest() {
            
            if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
                xmlhttp = new XMLHttpRequest();
            }
            else {// code for IE6, IE5
                xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            xmlhttp.onreadystatechange = function () {
                if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                    var response = xmlhttp.responseText;
                    document.getElementById("response").innerHTML = response;

                }
            }
            xmlhttp.open("GET", "somehtml.htm", true);
            document.getElementById("response").innerHTML = "Loading..";
            window.setTimeout("xmlhttp.send()", 1000);
        }
    </script>
</head>
<body onload="httprequest()">
    <form id="form1" runat="server">
    <div id="response"></div>
    </form>
</body>
</html>


This httprequest() Jscript function open “somehtml.htm” as async process and write its content / response to a div element (‘response’).
I create an instance of XMLHttpRequest (xmlhttp). There is a different method to create that instance depends on a browser type.
I use open() method to open a connection to a spesific page and then use send() to load it. If the load of page content is complete then its content’s string can be retrieved with xmlhttp.onreadystatechange callback function.

Before async process is begin I show a ‘Loading..’ message for a second (1000 ms) just to indicate something happen by using window.setTimeout(). This setTimeout halts a function execution for specified miliseconds.

The somehtml.htm:

<h2>Header</h2>
<b>Bold Text</b><br />
This is html page<br />

The result of aspx page will look like below

To load aspx file with XMLHttpRequest simply change arguments inside xmlhttp.open(). But we have to delete the <html>, <body>, <form runat=server> tags in .aspx file due to we want to display the other aspx page inside div element.
We already have those tags in parent page.

Example of aspx file:

<% Response.Write("<h2>Header of Aspx file</h2>")
Response.Write("<b>Hello world</b>") %>

Basicaly I write any string in aspx file using Response.Write function to write in this page. This file is similar with Asp Classic file. In fact, we can write a Asp Classic and load it using ajax.

We have more elegant method to accompany traditional ajax which is using Generic Handler or .ashx file. This Generic Handler does not generate a Web Form, so it is a good option for dynamic Asp.Net file and minimal web pages.
Also this generic handler can return or show a dynamic image, write XML and any other data.

Just click ‘Add New Item’ and then ‘Generic Handler’, VS will automatically generate code for us. To shorten my explanation, this handler implements IHttpHandler interface. One of the procedure we have to consider is ProcessRequest().
Basicaly we can code anything like showing arbitrary string with Context.Response.Write function, connect to database, viewing an image, all of these code is written inside ProcessRequest() procedure.

Example of .ashx file:

Imports System
Imports System.Web

Public Class somehandler : Implements IHttpHandler
    
    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
        context.Response.ContentType = "text/html"
        context.Response.Write("<h2>Handler header</h2>")
        context.Response.Write("<b>Bold text</b><br>")
        context.Response.Write("Hello World")
        
    End Sub
 
    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return False
        End Get
    End Property

End Class

Above handler show a static html only. We can set the header of content by setting context.Response.ContentType property value i.e text/plain, text/html, image/png etc.
With handler, we do not need to delete <html>, <form runat=server>, <head>, <body> tags like in .html or .aspx file.

The JS script httprequest() function above will only change to the Url that pointed to the handler’s .ashx address:

function httprequest() {            
		//... 
		xmlhttp.open("GET", "somehandler.ashx", true);
		//...
	}

Run it and the result will be the content of that handler.

ScriptManager & PageMethods As A Modern Ajax Approach

Asp .Net Extension has a bunch of Ajax Control. The must have control is ScriptManager. ScriptManager enables modern Asp.Net Ajax functionality. With ScriptManager we can code ajax process both on server side an client side development.
Traditional ajax does not need ScriptManager but client XmlHttpRequest and off course it use client side development only.

In this post, I use modern client side development (PageMethods) to compare with traditional method. PageMethods calls server side code from client code. We do not need another file like before to write a server method.
Client script can interact with server / code behind aspx file functions in single aspx. This will increase developers productivity. Single aspx means you dont have to create another file by your own for a code file.
As you already know, every aspx file may contains two individual files which are .aspx and .aspx.vb / .aspx.cs files. This generated automatically by VS.

Please take a note that server side function is a public static / shared function and must have <WebMethod()> attribute.

Here’s a example of using PageMethods (.aspx) at a client level:

<form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
        </asp:ScriptManager>
        <script language="javascript" type="text/javascript">
            Sys.Application.add_load(page_load);
          
            function page_load(sender, e) {
                $get("response").innerHTML = "Loading..";
            }

            function ajaxrequest(mytext) {
                window.setTimeout("usePageMethods('" + mytext + "')", 1000);                
            }

            function usePageMethods(mytext) {
                var req = PageMethods.ServerRespStr(mytext, 
					function (success_response) {
						$get("response").innerHTML = success_response;
					},  
					function (fail_response) {
						 alert(fail_response.get_message());
					}
				);
            }
            ajaxrequest("my own text");    
    </script>
        <div id="response"></div>
        
    </div>

Above code has ScriptManager control with EnablePageMethods attribute set to true. This is necessary to enable PageMethods on client script.

I use Sys.Application.add_load(page_load); to register a page_load method as a startup function that executes when ajax is begin. page_load(sender, e) method set div element to show ‘Loading ..’ message. So at every ajax request is begin, page_load(sender, e) function executes and that loading message will appear. Also notice that I refers the div element with $get shortcut to shorten my code. This only available if we have ScriptManager control which means tradional ajax does not have it.

Note: To know more about Asp.Net Ajax Client Development please click this link: Introduction To Asp .Net Ajax Client Side Development ($get, $addhandler, $removehandler, Sys.Application, Sys.WebForms, Sys.Net)

I have ajaxrequest(mytext) that calls usePageMethods() in a second and usePageMethods() runs a PageMethods. This ajaxrequest function will runs at the document directly.

As a brief, PageMethods calls server side function by write its name after PageMethods static class in client script. Lets say I have a Server side / code behind aspx file function ServerRespStr.
I want to call that ServerRespStr from client script, so I do this PageMethods.ServerRespStr(<function_argument>,<success_callback>,<fail_callback>).
The <function_argument> is parameter(s) of ServerRespStr(), <success_callback> is a function that execute if related server function returning success otherwise <fail_callback> function will execute.
<success_callback> and <fail_callback> is optional so if you dont specify them then you dont have response either it is success or not.
This PageMethods also run in async mode.

You can write that function_argument as many as you want not only one. Just list it with ‘,’ delimiter after each of them sequencely. Remember this function_argument is an input for server side function argument.

The success_callback method will write a returned string in div element with id=’response’. If an error happens then PageMethods triggers fail_callback method and alert the error message.

I write those callbacks body in above code directly as PageMethods argument. However I also can write them with a function name only.
Please look below code:

<form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true">
        </asp:ScriptManager>
        <script language="javascript" type="text/javascript">
            Sys.Application.add_load(page_load);
          
            function page_load(sender, e) {
                $get("response").innerHTML = "Loading..";
            }

            function ajaxrequest(mytext) {
                window.setTimeout("usePageMethods('" + mytext + "')", 1000);                
            }

            function usePageMethods(mytext) {
                var req = PageMethods.ServerRespStr(mytext, success_callback, fail_callback);					
            }

            function success_callback(success_response) {
                $get("response").innerHTML = success_response;
            }
			
	   function fail_callback(fail_response) {
                alert(fail_response.get_message());
            }

            ajaxrequest("my own text");    
		</script>
        <div id="response"></div>
        
    </div>

So I have two callbacks function with their name as arguments of PageMethods. The result of this file is same as before.

Lets take a look at Server side function code:

Imports System.Web.Services
Partial Class PageMethod
    Inherits System.Web.UI.Page

    <WebMethod()> _
    Public Shared Function ServerRespStr(ByVal yourtext As String) As String
        Dim sb As New StringBuilder()
        sb.Append("<h2>PageMethod example header</h2>")
        sb.AppendLine("<b>Bold text</b><br>")
        sb.AppendLine("Hello world -> " & yourtext)
        Return sb.ToString()
    End Function

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    End Sub
End Class

As you can see that I have ServerRespStr(byval yourtext as String) function with <WebMethod()> attribute. This function have one argument only but you can add it as many as you want.
It returns simple string only that contains html tags. This returned string will stored as a response string in success_callback client function if the server function successfuly executed or contains no error.
Otherwise if the server function has error(s) then fail_callback client function will have its error response. The error message can be accessed in that fail_callback function.

I also imports System.Web.Services so that I dont have to write the full namespace in <WebMethod()> attribute.

Just Run this website application and the result look like below

Regards,
Agung Gugiaji

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s