Ajaxism! Making your ASP.NET application Ajax enabled. (1)


Many ASP.NET developers believe that AJAX is equal to putting an update panel on a form and using it! I do not blame those programmers because Microsoft Ajax Extensions has come to ease the process of making a web site Ajax enabled and making Ajaxing procedures transparent. However, I believe every developer must know about the Ajax itself and its mechanism. Moreover, if we know about the drawbacks of using UpdatePanel, we might decide to write our own Ajax code.

What is AJAX?

The word Ajax is the abbreviation of Asynchronous Javascript and XML. In general, it means to use XML and Javascript in order to create interactive web applications. In the classic web model, the browsers posts some data to server and server sends a resul HTML code back to the browser. To view the results, your browser has to refresh the page. This makes the whole page content be transferred from server to client. Whilst in many cases only a very small part of the page must be refreshed. For example, suppose there are two DropDownList control on a page. One for countries (ddlCountry) and one for Provinces (ddlProvince). We need to refresh the ddlProvince items according the ddlCountry selected item. Should we post back the whole page to the server? Should we send the whole page from server to client? Using Ajax we just refresh ddlProvince and fill it with proper items.

In order to read a complete description of Ajax please refer to Wikipedia here:

http://en.wikipedia.org/wiki/AJAX

How to implement Ajax?

In Ajax world, everything is based on something named XMLHttpRequest. The XMLHttpRequest object is the key to AJAX. It has been available ever since Internet Explorer 5.5 was released in July 2000, but not fully discovered before people started to talk about AJAX and Web 2.0 in 2005.

XMLHttpRequest (XHR) is an API that can be used by JavaScript, JScript, VBScript and other web browser scripting languages to transfer and manipulate XML data to and from a web server using HTTP, establishing an independent connection channel between a web page’s Client-Side and Server-Side.

How to use it?

Inside IE, XmlHttpRequest is created via an ActiveX. However other borwsers, like FireFox, has an internal mechanism to instantiate a XmlHttlRequest object. Of course IE 7 provides a FireFox-like method to create XmlHttpRequest so that we do not have to check the browser type.

In IE:

var xmlHttp = null;

xmlHttp = new ActiveXObject(‘Microsoft.XMLHttp’);

Other Browsers:

var xmlHttp = null;

mlHttp = new XMLHttpRequest();

we can write a function ( in JavaScript) to do it:

var xmlHttp = null;

function CreateXMLHttpRequest()

{

if(window.ActiveXObject)

{

xmlHttp = new ActiveXObject(‘Microsoft.XMLHttp’);

}

else

{

xmlHttp = new XMLHttpRequest();

}

return xmlHttp;

}

As I mentioned before, you may use new XMLHttpRequest(); in IE 7+.

Now we are ready to send a request to Server and get a response from it. We may use this with XmlHttpRequest.Open method. This method takes three arguments:

1-‘GET’ or ‘POST’. Which approach is used to exchange data with server.

2- The URL on server.

3- True/False. Indicates is the communication with server Asynchronous or not. If you specify True, the open method will not wait for the response.

For instance, we may write this code:

xmlHttp.Open(‘GET’, ‘FetchUsers.aspx?ID=1’,true);

Afterwards we must wait for the response from the server. We are notified of a change in XmlHttp object with “onreadystatechange” event. This event belongs to XmlHttpRequest and we have to handle it. To do this, just write a JavaScript function and assign it to this event:

xmlHttp.onreadystatechange=update;

function update()

{

//some code here

}

What does update() function do? In such a function or better say such an event handler, we must check the value of readyState property. This property belongs to XmlHttpRequest and indicates what is going on! The possible values of this property are as follows:

0 or uninitialized

Object is not initialized with data.

1 or loading

Object is loading its data.

2 or loaded

Object has finished loading its data.

3 or interactive

User can interact with the object even though it is not fully loaded.

4 or complete

Object is completely initialized.

Well, needless to say that the server response is ready-to-use only if the readyState is 4.

Inside the Update() function we can do whatever we feel like, if readyState is 4:

if (xmlHttp.readyState ==4)

{

var msg=xmlHttp.responseText;

document.getElementById(‘lblHello’).innerText= msg;

}

Please look at the above code. The code shows that we have received the server response with responseText property. We may also receive an XML formatted response with responseXML. If you might have non-English characters in your response, I strongly recommend you to pass Data in XML format with utf-8 encoding.

The 2nd line above shows that the response has been assigned to innerText property. innerText is somehow equal to .Text property of a Label or Textbox control. You may use it if your response is Plain Text only. If your response is in html format you must assign it to innerHTML property.

That is it! You may write a small JavaScript function and assign it to any desired event, like onclick, ondblclick, onmouseover,on keyup and… to invoke your Ajax code.

However we must know that where the server response comes from? As the above example shows we get the response from FetchUsers.aspx. Whatever that FetchUsers.aspx writes into its Response object will be put in responseText property of XMLHttpRequest. By the way, the overhead of .aspx pages is too much I personally prefer to use Generic Handlers (.ashx). Generic Handlers are very flexible and lightweight . Therefore I will talk about them later on separate posts.

Let’s see the rest of the tutorial in action. I have written a sample code that you may download from HERE. This ASP.NET 2.0 website get’s your name and says you hello in an AJAX way 🙂 The source of JavaScript part of this implementation is here:

<%@ Page Language=”C#” AutoEventWireup=”true”  CodeFile=”Default.aspx.cs” Inherits=”_Default” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;

<html xmlns=”http://www.w3.org/1999/xhtml&#8221; >
<head runat=”server”>
<title>ASPGY.WORPRESS.COM</title>
<script type=”text/javascript” language=”javascript”>
var xmlHttp = null;
function CreateXMLHttpRequest()
{
if(window.ActiveXObject)
{
xmlHttp = new ActiveXObject(‘Microsoft.XMLHttp’);
}
else
{
xmlHttp = new XMLHttpRequest();
}
return xmlHttp;
}
function process()
{
document.getElementById(‘lblHello’).innerText=”loading…”;
CreateXMLHttpRequest();
if (xmlHttp != null)
{
var uname=document.getElementById(‘TextBox1’).value;
xmlHttp.onreadystatechange=update;
xmlHttp.open(‘GET’,’process.ashx?name=’+uname, true);
xmlHttp.send();
}
else
alert(‘your browser does not support ajax’);
}
function update()
{
if (xmlHttp.readyState ==4)
{
var msg=xmlHttp.responseText;
document.getElementById(‘lblHello’).innerText=msg;
}
}
</script>
</head>
<body>
<form id=”form1″ runat=”server”>
<div>
<span style=”font-size: 16pt; color: #ff0066″><strong>AJAX Sample</strong></span><br />
<br />
<span style=”font-size: 9pt; font-family: Tahoma”>Enter name</span>:
<asp:TextBox ID=”TextBox1″ runat=”server” onkeyup=”process()”></asp:TextBox><br />
<asp:Label ID=”lblHello” runat=”server” Font-Names=”tahoma” Font-Size=”9pt” ForeColor=”Blue”></asp:Label></div>
</form>
</body>
</html>

You may also download a PDF version of this post HERE.


Advertisements

How to open popup windows in IE/Firefox and return values using ASP.NET


Recently, a friend of mine asked about how to open popup (modal) windows in IE/Firefox and return the values back to the main page. although there are tons of question/answers about this subject in ASP.NET forums, nearly none of them was comprehensive enough. For this reason and to answer my friend’s question I am going to explain how to open a dialog box, how to pass initial values to this dialog box, how to get the values back and so on.

Internet Explorer(IE) contains the showModalDialog() method which proves very effective while creating a modal dialog box and displaying a html document in it. Dishearteningly, showModalDialog() is not a W3C implementation. So it is not supported in Firefox. Firefox supports the window.open() method. However there is no built in functionality in Firefox that keeps the popup modal. At the most, you can use ‘modal=yes’ to make the popup appear in front. However unlike the showModalDialog() in IE, you cannot restrict the user to access the parent page when the popup is opened in Firefox. In short, it is not truly modal. There are different ways to get around this problem, however in this article, we will only focus on exchanging values between the parent and popup page.

I have written a small but exhaustive sample web site whose link is shown at the end of the article.

As it was mentioned earlier, to open a dialog we can use showModalDialog (for IE) or window.open (for FireFox) JavaScript functions to open a dialog. Both functions take 3 arguments:

  1. The URL of the page to show.
  2. Caption of the dialog window.
  3. Settings of the dialog window.

The most used setting items are as follows:

  • center: yes/no (indicates weather the dialog must be screen centered)
  • resizable: yes/no (indicates weather the dialog window is resizeable)
  • status: yes.no (indicates weather a Status Bar is added to the dialog window)
  • dialogWidth: n (the width of the pop up window. like : 300px)
  • dialogHight: n (the hight of the pop up window. like : 200px)

Both window.Open and window.showModalDialog functions return a value . This value is set within the called page (dialog page) by assigning the result value to window.returnValue. However, since we are ASP.NET developers, we are most likely to use the result in Server-Side code so I do not feel like very much to get the result value with JavaScript code.

By the way, write a JavaScript function and call it whatever you wish, like OpenDialog(), and put it in <head>…</head> section of your caller (main) page:

function OpenDialog()
{
window.showModalDialog(‘Child.aspx’,”,’center:yes;resizable:yes;

status:no;dialogWidth:3030px;dialogHight:200px’);
}

the above example indicates that OpenDialog function will open Child.aspx in a modal window whose width is 300px .

Now at your caller page, put a Button and name it btnOpenDialog. Afterwards go to properties window and put the following line next to OnClientCliek property:

javascript:OpenDialog();

To create the pop-up window we must create a page named Child.aspx. In my demo code, I have put a CheckListBox there with 3 items (Apple, Orange and Banana) in it. We also need two buttons named btnOK and btnCancel.

We do not need to write anything on code behind for btnCancel. All we have to do is to write the following code snippet into btnCancel.OnClientScript property:

javascript:window.close();

In order to return a value, we can assign it to window.returnValue property but I really don’t feel like to do it because in most cases we obtain this value from some server-side code (we are ASP.NET developers!) and if we insist on using window.returnValue , we will have to mixup some server-side and client-side code together which makes our code unclear.Moreover, .returnValue is not suitable to return complex results like ILIST colelctions. By the way if you stress on using this method, take a look ad window.opener and window.returnValue properties at MSDN.

Anyway, lets go back to our code. For btnOk button we don’t assign a JavaScript code to it because we have to calculate somethings and put it in session variable before the pop-up window is closed. Therefore, in the code behind and in OnClick event of btnOk button write a code like this:

// GatherAllSelected is a method to get selected items. You can write any similar function to do this.

IList<string> Result = GatherAllSelected();

// we put the list into Session object
if (Session[“Selected”] != null)
Session[“Selected”] = Result;
else
Session.Add(“Selected”, Result);

// a code to be run in client-side
string scriptStr = “<script>window.close();</script>”;

// send the script to output stream
ClientScript.RegisterClientScriptBlock(typeof(string), “closing”, scriptStr);

What does the above code do for us? First, a method named GatherAllSelected prepares the value to be returned. You can write your own method with any return type. Then, we put the result value into Session object. If we decided to user window.returnValue we could not return complex results unless we serialized them. That would be a hell indeed.

At the end we have to close the the pop-up window. Since the client-side code of a Button is always executed before the server-side code we can not write window.close(); in btnOK’s OnClientClick property. Instead, we generate a small JavaScript code , and send it to client by ClientScript.RegisterClientScriptBlock method. This will make our script run and consequently close the dialog.

After the dialog is closed, the OnClick event of our called button (btnOpenDialog) is called. In it, we can retrieve our expected value from Session object and use it:

protected void btnOpenDialog_Click(object sender, EventArgs e)
{
if (Session[“Selected”] != null && Session[“Selected”].ToString() != “”)
{
lblResult.Text = “”;
IList<string> Result = Session[“Selected”] as IList<string>;
foreach (string item in Result)
lblResult.Text += item + “\n”;
Session[“Selected”] = “”;
}
}

Important note:

If you run the above example, when you click on btnOK button (on child.aspx) nothing will happen! Even, if you do something that posts back your page, a new window will be opened!

How to solve it?

To sort this problem out simply put the following line in the child.aspx’s HEAD section:

<base target=”_self”/>

This code will make the new page open in the same window.

How to pass initial values to the pop-up window?

For this we can use Request.QueryString property but we also need to change our method a little bit. In Child.aspx and at Page_Load even handler, check the QueryString property and retrieve your initial values. The following sample code is doing it:

if (!IsPostBack)
{
string SelectedList = “”;
if (Request.QueryString[“Selected”] != null)
SelectedList = Request.QueryString[“Selected”];
string[] items = SelectedList.Split(‘,’);
foreach (string item in items)
clbFruit.Items.FindByValue(item).Selected = true;
}

This code assumes that the initial values are seperated by commas. So it will split them into a string[] array and use them in a proper way.

If your initial values are not constant and they are calculated in your code behind, you will have to remove the OpenDialog() method from caller.aspx page. You also must remove the value of btnOpenDialog.OnClientClick property. Otherwise you will get a script error whenever this button is clicked.

After removing these values, write a code like this in caller.apx’s Form_Load event:

if (!IsPostBack)

{

string ScriptBody=‘Child.aspx?InitialValues={0}’;

:

:

}

Then calculate your initial values and shape them in a comma separated string (i.e. ‘Banan,Apple’). Afterwards, format ScriptBody variable to include your initial value string:

ScriptBody = String.Format(ScriptBody , ‘Banana,Apple’);

Well, now you must send a window.showModalDialog or window.Open command yo the client. This approach is good also because in your code behind you can simply detect the browser type and change your script code easily to be compatible with Firefox or IE.

Anyway, again send your script to client by ClientScript.RegisterClientScriptBlock method:

string FinalScript = “<script> window.showModalDialog( “+ ScriptBody + “, ” ,’center:yes;resizable:yes;status:no;dialogWidth:3030px;dialogHight:200px’);</script> “;

ClientScript.RegisterClientScriptBlock(typeof(string), “closing”, FinalScript );

That’s it! You can download my sample code HERE and see how it works.

Thanks,

Aref Karimi