Microsoft Ajax, from the bottom up - part 3
Hi all again, hope you had a great holiday vacation :-)
In this next post i will do my very best to move on and finally introduce Microsoft Ajax. For those who missed the first 2 previous post about ajax, you can read them here:
Microsoft Ajax, from the bottom up
Microsoft Ajax, from the bottom up - part 2.
As a reminder , we are now able to create web applications based on ajax and avoid the tedious flickering and flashing during postbacks. we now want an easier way to do an Async calls to partially update our web page.
As Microsoft writes in their official asp.net site ,Microsoft Ajax is
"ASP.NET AJAX is a free framework for quickly creating efficient and interactive Web applications that work across all popular browsers"
Or in other words, it is a framework for better ,quicker way for writing ajax based application which are more efficient and which have support for cross browsering.
As we shall see next , ASP.NET Ajax is built out of 2 half's:
1.A server half, usually referred to as "ASP.NET AJAX Extensions" which contains among other many things 5 server controls, some of them you probably know : The ScriptManager , UpdatePanel, UpdateProgress, Timer and ScriptManagerProxy. (BTW many other controls were intended to be released on the last version of ASP.NET but Microsoft team decided not to include them this time)
This half is also supports ASMX Web methods as endpoints for asynchronous AJAX callbacks.
We are going to talk mainly about this half in the next posts.
2. A client Half , usually referred to as "Microsoft Ajax Library".
This half among other things is responsible for :
- Making our Async calls browser independent.
- Enhancing Javascript with .NET like type system . such as Namespaces, Classed, Inheritance an even extending the native objects in javascript such as String, Array , Date etc. so we could even code something like that:
alert(String.format("may name is {0}","pini"));
or even use a StringBuilder object in javasctipt. all of this is not new to javascript at all and is all base on javascript prototyping which you can read much more about here for sample:Advanced javascript
- New out of the box Drag and drop capacities, animations.
3. It it worth mentioning here the ASP.NET Ajax control toolkit.This is a separated installation for creating and using out of the box controls that already being written for us.These are ajax based controls or even controls are not even connected to ajax, such as : AutoCompleteTextBox, WaterMarkTextBox, Expando menu , ModelWin and much more.
From all the excitement i forgot to start and really show some of the things, so lets begin with the most familiar and popular server control Microsoft has to to offer: the UpdatePanel control.
The UpdatePanel control:
The UpdatePanel control is really a "partial page rendering in a box".
Partial-page rendering reduces the need for synchronous postbacks and complete page updates when only part of the page has to be updated.
Using this control does not require any javascript knowledge and it is suitable for cross browsers application as well.
When we want to avoid postback to the server and do our work in an ajax way, all we need to do is place an UpdatePanel control on the page (along with a ScriptManager control) and every postback that will be generated from any control inside this UpdatePanel will now do an Async call to the server and update the UI for us. More over, we can specify that other controls on the page that are not within the UpdatePanel control, will now cause a visual postback for us but instead will perform Async calls. There is a great flexibly for controlling different situations.
Lets see some sample, This sample will contain a dropdown list control that has a onselectedindexchanged event set up to go to the server and update some label according to the selected value:
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptManager1"
EnablePartialRendering="true"></asp:ScriptManager>
<div dir="rtl">
<br />
<asp:UpdatePanel runat=server ID="upUpdatePanel1">
<ContentTemplate>
<asp:DropDownList runat="server" ID="ddlEmployees"
onselectedindexchanged="ddlEmployees_SelectedIndexChanged"
AutoPostBack=true>
<asp:ListItem Text="pini" Value="pini"></asp:ListItem>
<asp:ListItem Text="zohar" Value="zohar"></asp:ListItem>
<asp:ListItem Text="eran" Value="eran"></asp:ListItem>
</asp:DropDownList>
<br />
<asp:Label runat="server" ID="lblDetails" ></asp:Label><br />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
As you can see all the aspx code in this sample is inside the UpdatePanel control.
This fact will cause an Async Call to the server whenever the user changes the select box value.
Lets see the server code:
protected void ddlEmployees_SelectedIndexChanged
(object sender, EventArgs e)
{
string sDetails = @"<UserData><Name>{0}</Name><Age>{1}</Age>
<Hobbies>{2}</Hobbies></UserData>";
string sResult = string.Empty;
switch (((DropDownList)sender).SelectedValue)
{
case "pini":
sResult = string.Format(sDetails,"pini","30",
"Soccer,Dancing");
break;
case "zohar":
sResult = string.Format(sDetails,"zohar","25",
"Ballete,Tennis");
break;
case "eran":
sResult = string.Format(sDetails,"eran","15",
"Programming,Dancing");
break;
default:
sResult = string.Empty;
break;
}
lblDetails.Text = sResult;
}
If you try and run this sample you will see no flashing and flickering at all.
And we didn't write a single javascript code at all.
In order to enable partial page rendering in our web page, we need to tell the ScriptManager in the page to do so, this is done by setting the EnablePartialRendering property to "true". Luckily for us the default value is "true" so we don't really have to do anything.
Lets move on. What if we want other controls on the page that are not within the UpdatePanel (but do affect the content of the controls inside our UpdatePanel ) to do a partial page rendering as well? The answer is we sure can!
The UpdatePanel controls has a "Triggers" Section inside it to do just that.
Lets change our previous sample a bit, this time we will only change the aspx code:
<form id="form1" runat="server">
<asp:ScriptManager runat="server" ID="ScriptManager1"
EnablePartialRendering="true"></asp:ScriptManager>
<div dir="rtl">
<asp:DropDownList runat="server" ID="ddlEmployees"
onselectedindexchanged="ddlEmployees_SelectedIndexChanged" AutoPostBack=true>
<asp:ListItem Text="pini" Value="pini"></asp:ListItem>
<asp:ListItem Text="zohar" Value="zohar"></asp:ListItem>
<asp:ListItem Text="eran" Value="eran"></asp:ListItem>
</asp:DropDownList>
<br />
<asp:UpdatePanel runat=server ID="upUpdatePanel1">
<ContentTemplate>
<asp:Label runat="server" ID="lblDetails" ></asp:Label>
<br />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlEmployees"
EventName="SelectedIndexChanged" />
</Triggers>
</asp:UpdatePanel>
</div>
</form>As you can see, this time the dropdowlist control is not part of the UpdatePanel , but we want his selectedindexchange event to perform a partial page update for us, so all we need to do , is add <asp:AsyncPostBackTrigger ControlID="ddlEmployees" EventName="SelectedIndexChanged" /> to the "Triggers" Section.
We need to specify the control id causing the event, the event name (or omit this property if it is the default event, such as Click for Button).
The "Triggers" section can also contain asp:PostBackTrigger control instead of the asp:AsyncPostBackTrigger but i will talk about it later.
As it turns out, there are many other situations ,such as:
- We have several UpdatePanel controls on the page and we want to change the content of one of them whenever some other UpdatePanel is being updated.
- We have several UpdatePanel controls on the page and we want to change only one of them.
- We want to update our UpdatePanel control only when some condition occur.
- We want controls within our UpdatePanel not to cause a postback.
- You have 2 UpdatePanel controls and you want a postback from the first panel to update the content only of the second one but not update it's own content.
In order explain the different situation i will summaries it all using the Microsoft documentation and some samples:
-
If the UpdateMode property of the UpdatePanel control is set to Always, the UpdatePanel control's content is updated on every postback that originates from the page. This includes asynchronous postbacks from controls that are inside other UpdatePanel controls and postbacks from controls that are not inside UpdatePanel controls.
- If the UpdateMode property is set to Conditional, the UpdatePanel control's content is updated in the following circumstances:
When you call the Update() method of the UpdatePanel control explicitly.
When the UpdatePanel control is nested inside another UpdatePanel control, and the parent panel is updated.
When a postback is caused by a control that is defined as a trigger by using the Triggers property of the UpdatePanel control. In this scenario, the control explicitly triggers an update of the panel content. The control can be either inside or outside the UpdatePanel control that the trigger is associated with.
When the ChildrenAsTriggers property is set to true and a child control of the UpdatePanel control causes a postback. Child controls of nested UpdatePanel controls do not cause an update to the outer UpdatePanel control.
Lets see a simple sample that explains the Conditional mode:
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional"
runat="server">
<ContentTemplate>
<p>
The content in this UpdatePanel only refreshes When the Button2 is clicked.
updated: <strong>
<asp:Label runat=server ID="lblTime1"></asp:Label>
</strong>
</p>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button2" />
</Triggers>
</asp:UpdatePanel>
<asp:UpdatePanel ID="UpdatePanel2" runat="server"
UpdateMode=Always>
<ContentTemplate>
<p>
This UpdatePanel always refreshes if the button is clicked.
Last updated: <strong>
<asp:Label runat=server ID="lblTime2"></asp:Label>
</strong>
</p>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Button1" />
<asp:AsyncPostBackTrigger ControlID="Button2" />
</Triggers>
</asp:UpdatePanel> <asp:Button ID="Button1" Text="Button1"
runat="server" OnClick="Button1_Click" />
<asp:Button ID="Button2" Text="Button2"
runat="server" OnClick="Button2_Click" /> </div>
Here we have 2 UpdatePanel controls , each containing a Label.The first panel is set to Conditional mode and the second one is set to Always mode.Notice also that the second one adds the buttons to the Triggers while the first one adds only the second button(Button2)
Now lets look at the cs code:
protected void Button1_Click(object sender, EventArgs e)
{
//Will only update the second panel
lblTime1.Text = DateTime.Now.ToString();
lblTime2.Text = DateTime.Now.ToString();
//if we want to update the first one as well unmark this:
//UpdatePanel1.Update();
}
protected void Button2_Click(object sender, EventArgs e)
{
lblTime1.Text = DateTime.Now.ToString();
lblTime2.Text = DateTime.Now.ToString();
}
As you can see , When we click Button2, Both of the panels will be updated.When we click Button1 only the second panel will be updated.
This is because the Button1 is outside the panel and he is not specified in the Triggers section.
In the next post i will do my very best to move on to the UpdateProgress control.
Enjoy :-)