Significance of ScriptManager
The scriptmanager plays the pivotal role in the
functioning of the update panel which does all the client stuff required. The
primary role of the script manager is to support all the asp.net ajax controls
which renders the scripting utilities to the browser and does the client side
operations on a web browser. The ScriptManager control acts as a global
registrar of sorts for all the services you need in your ASP.NET AJAX
application. It actually performs asynchronous communication with the code
running on the client so that the script can perform the necessary page
updates.
The following points explain about script manager:
1. Scriptmanager understands the
partial postbacks and does the partial rendering.
2. Using scriptmanager we can
control the postback of the control to asynchronous, and also make the postback
of the controls which is in updatepanel synchronous.
3. Using scriptmanager we can
update the control of the page which is outside of the updatepanel when the
asynchronous postback is done within the updatepanel.
4. We can now asynchronously
interact with Web services from script in ASP.NET AJAX using ScriptManager. It
will return a script class wrapping the methods of the Web service (this is
known as proxy script).
JSON Importance
Javascript Object Notation is a data exchange format
which is used for asynchronous communication between client and the server,
updatepanel sends data in Json for its communication. The Json format is human
readable which is a collection of name/value pairs. The Asp.Net Ajax uses JSON
for its data interchange between client and the server. The primary advantage we
get using JSON is bandwidth optimization. The scriptmanager and the updatepanel
will understand the JSON format and execute the http request to render back
response to the browser.
UpdatePanel How It Works?
Now we will delve into updatepanel and its stuff using
some samples lets take a simple web form. Drag a updatepanel onto the webform
then place a button control and label control inside the updatepanel.
The markup looks like this:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label
ID="Label1" runat="server" Text="Label"></asp:Label>
<br
/>
<asp:Button
ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
</ContentTemplate>
</asp:UpdatePanel>
On the Button click event I am changing the Label text
to some value as given below
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Suresh Kumar";
}
Now when we click on the button which is inside the
updatepanel, the label text is updated with value assigned in the server code.
Notice that there was no postback occurred and no re-rendering of the entire
page took place. The entire httprequest is executed through asynchronous
postback and response is rendered using the partial rendering.
Scriptmanager when it renders for the first time,
registers the client side runtime useful for making the asynchronous postbacks.
This client script is written to the page output through a method called
RenderPageRequestManagerScript.
If we observe the request through fiddler we can see how
the http protocol is sent to the server and how the server sents back the
partial response.
Http protocol:
POST
http://ssss-d6f1520724/UpdatePanelSampless/UpdatePanelSample1.aspx HTTP/1.1
Accept: */*
Accept-Language: en-us
Referer:
http://ssss-d6f1520724/UpdatePanelSampless/UpdatePanelSample1.aspx
x-microsoftajax: Delta=true
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT
5.1; Trident/4.0; GTB6.6; .NET CLR 1.1.4322; Zango 10.3.36.0; .NET CLR
2.0.50727; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Host: ssss-d6f1520724
Content-Length: 224
Connection: Keep-Alive
Pragma: no-cache
ScriptManager1=UpdatePanel1|Button1&__EVENTTARGET=&
__EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwULLTEyNTU5OTE4NDBkZOixBLCMCOUKxe%
2F%2BB3f4nQsrF1tG&__EVENTVALIDATION=%2FwEWAgL%2B76ecDQKM54rGBuxpceXT2p
fd48oCEpiM8SNpawCL&Button1=Button
Response:
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Sun, 30 Jan 2011 04:12:45 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Transfer-Encoding: chunked
Cache-Control: private
Content-Type: text/plain; charset=utf-8
2a0
177|updatePanel|UpdatePanel1|
<span id="Label1">Suresh
Kumar</span>
<br />
<input type="submit" name="Button1"
value="Button" id="Button1" />
|116|hiddenField|__VIEWSTATE|/wEPDwULLTEyNTU5OTE4NDAPZBYCAgMPZBYCAgMPZBYCZg9k
FgICAQ8PFgIeBFRleHQFDFN1cmVzaCBLdW1hcmRkZBcU5rhqSUcVlgAh4HLQKuS714md|48|hiddenField
|__EVENTVALIDATION|/wEWAgLw/9KoCgKM54rGBh38yWELvcyI6330lnGUC/4gVi1B|0|
asyncPostBackControlIDs|||0|postBackControlIDs|||13|updatePanelIDs
||tUpdatePanel1|0|childUpdatePanelIDs|||12|panelsToRefreshIDs
||UpdatePanel1|2|asyncPostBackTimeout||90|23|formAction||
UpdatePanelSample1.aspx|13|pageTitle||Untitled
Page|
0
In the http request above we can see a http header which
is bold “x-microsoftajax:
Delta=true”
This special request with request header (x-microsoftajax
with a value Delta=true) indicates the server
to send markup only for the updates parts of the page. The Partial Rendering response viewer is activated when the
special header I just mentioned is detected.
The scriptmanager reads this
header and renders the response back to the client in the format that client
script understands. The scriptmanagers renders the client side runtime required
and initializes the PageRequestManager operating on the client with the exact
controls it should watch. The client side PageRequestManager takes the
responsibility of identifying the controls from which the postback has come from
and decides whether it is a normal postback or asynchronous post and based on
that sends the request to the server.
The http post request is sent
to the server using the client side utility Sys.Net.WebRequest. The asp.net
class Sys.Net.WebRequest provides the client script functionality to make the
web request.
Eg:
var wRequest = new Sys.Net.WebRequest();
wRequest.set_url(postPage);
wRequest.set_httpVerb("POST");
wRequest.invoke();
So now the request is sent to the server, the
scriptmanager on the server identifies the control which made the partial
postback. Now scriptmanager takes the responsibility of rendering the response
back to the client by overriding default Asp.Net page rendering.
By knowing what controls caused the postback and their
associations—is it in an UpdatePanel with other controls, or is the source of
the postback event somehow linked to an UpdatePanel?—the ScriptManager control
knows which child controls should be asked to render and which should be
ignored. Where the default behavior for a Page class in ASP.NET is to ask each
child control to render, ScriptManager will only ask those it deems
necessary.
Now the client gets the asynchronous response from the
server and the client side runtime parses the response and updates the controls
with the data on the browser. If we observe the above mentioned response when an
updatepanel is refreshed the entire content which is inside the updatepanel is
re-rendered back to the client.
Updatepanel UpdateMode property
UpdateMode property of updatepanel indicates
whether the updatepanel will refresh on every asynchronous postback or only as
the result of a specific action. The UpdateMode can have two values they are
Always and Conditional. By default the UpdateMode property value
is Always.
If the UpdateMode property is Conditional, the
updatepanel contents are updated in the following scenarios:
Ø
The asynchronous postbacks from the same updatepanel can refresh
the updatepanel content.
Ø
If the postback is caused by the trigger for that updatepanel
control.
Ø
When you explicitly call the UpdatePanel control's Update
method.
Ø
When parent panel UpdateMode is always and child panel are
conditional the parent panel properties are applicable to child updatepanel.
Ø
But when parent panel UpdateMode is conditional and Child
panel is always, the parent panel properties are not applicable.
If the UpdateMode is Always, UpdatePanel
control’s content is updated on every postback that originates from anywhere on
the page. This includes asynchronous postbacks from controls that are inside
other UpdatePanel controls, and postbacks from controls that are not inside
UpdatePanel controls.
Updating UpdatePanel contents programmatically
We can refresh the contents of the Updatepanel
programmatically irrespective of its UpdateMode property. The updatepanel has
method update() using which we can update the contents.
Eg:
Label1.Text = "Suresh
Kumar";
UpdatePanel1.Update();
Lets say I have updated there updatepanels
programmatically using an asynchronous postback, the three updatepanels are
refreshed.
UpdatePanel1.Update();
UpdatePanel4.Update();
UpdatePanel5.Update();
Observe the response through all the three panels markup
is rendered back.
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Sun, 30 Jan 2011 11:33:55 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Transfer-Encoding: chunked
Cache-Control: private
Content-Type: text/plain; charset=utf-8
500
225|updatePanel|UpdatePanel1|
<span id="Label1">Suresh
Kumar</span>
<br />
<span
id="Label2">Label</span>
<input type="submit" name="Button1"
value="Button" id="Button1" />
|101|updatePanel|UpdatePanel4|
<input type="submit" name="Button5"
value="Up4Button" id="Button5" />
|101|updatePanel|UpdatePanel5|
<input type="submit" name="Button6"
value="Up5Button" id="Button6" />
|108|updatePanel|UpdatePanel2|
<input type="submit" name="UP2Button1"
value="UP2Button1" id="UP2Button1" />
|
Updatepanel Triggers
We can define triggers for an updatepanel. Let’s we have
a requirement that for a particular button click which is inside another
updatepanel the current updatepanel should be refreshed. Just add a triggering
event for the updatepanel. The markup looks as follows:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label
ID="Label1" runat="server" Text="Label"></asp:Label>
<br
/>
<asp:Label
ID="Label2" runat="server" Text="Label"></asp:Label>
<asp:Button
ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="UP2Button1" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
Now when you change the updatepanel1’s content in the
Up2Button1 click event the updatepanel1 is refreshed irrespective of its
UpdateMode property is Always or Conditional.
We can also add triggers to updatepanel
programmatically in the following way:
AsyncPostBackTrigger upnlTrigger = new AsyncPostBackTrigger();
upnlTrigger.ControlID = "UP2Button1";
UpdatePanel1.Triggers.Add(upnlTrigger);
In this case the two updatepanel contents are refreshed,
the updatepanel which called asynchronous postback the one which has the trigger
attached to the event. When we observer through fiddler both the updatepanels
contents are rendered back. Check this
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.1
Date: Sun, 30 Jan 2011 10:48:46 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Transfer-Encoding: chunked
Cache-Control: private
Content-Type: text/plain; charset=utf-8
3bb
225|updatePanel|UpdatePanel1|
<span id="Label1">Suresh
Kumar</span>
<br />
<span
id="Label2">Label</span>
<input type="submit" name="Button1"
value="Button" id="Button1" />
|108|updatePanel|UpdatePanel2|
<input type="submit" name="UP2Button1"
value="UP2Button1" id="UP2Button1" />
Both the updatepanels contents are rendered back to the
client.
We can also make control which is in updatepanel to a
synchronous post back using the Postback trigger. Check the markup:
<Triggers>
<asp:PostBackTrigger ControlID="Button1"
/>
</Triggers>
This behaves like the normal post of the page. When we
observer through fiddler the raw request looks like this
POST
http://ssss-d6f1520724/UpdatePanelSampless/UpdatePanelSample1.aspx HTTP/1.1
Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg,
application/x-shockwave-flash, application/vnd.ms-excel,
application/vnd.ms-powerpoint, application/msword, application/x-ms-application,
application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml,
*/*
Referer:
http://ssss-d6f1520724/UpdatePanelSampless/UpdatePanelSample1.aspx
Accept-Language: en-us
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT
5.1; Trident/4.0; GTB6.6; .NET CLR 1.1.4322; Zango 10.3.36.0; .NET CLR
2.0.50727; InfoPath.2; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Host: ssss-d6f1520724
Content-Length: 239
Connection: Keep-Alive
Pragma: no-cache
Notice that the x-microsoftajax: Delta=true is
missing when the postback is made synchronous using triggers of updatepanel
though it is inside updatepanel.
Programatically Controlling the Postbacks without
Triggers
We can also programmatically control postbacks of the
controls and make them synchronous and asynchronous based on the requirement.
Here the interesting point is we can make control to do asynchronous postback
though it is not inside any updatepanel.
Eg:
ScriptManager1.RegisterAsyncPostBackControl(LinkButton1);
Here though it is made asynchornous we can only update
controls which are inside the updatepanels only, even though we attempt to
update a control which doesn’t belong to any updatepanel the response is not
rendered to client. Let’s say we register a control to do a aysnchronous
postback the scriptmanager takes the responsibilty and registers it as
asychronous postback control. When we register the LinkButton1 as asynchronous
the following code is rendered to client:
Sys.WebForms.PageRequestManager.getInstance().
_updateControls(['tUpdatePanel1','tUpdatePanel2'],
['LinkButton1'], 90);
In the same way we can
register a control to do synchronous postback which is inside an updatepanel
without using triggers.
Eg:
ScriptManager1.RegisterPostBackControl(Button1);
Here the control behaves as the normal postback and
renders the entire response to the client.
Nested Updatepanels
Updatepanels can be nested that means we can place one
updatepanel inside another updatepanel.
So if the parent panel is refreshed all the nested
panels in it are also refreshed.
The markup looks like this,
<asp:UpdatePanel ID="UpdatePanel3" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Label
ID="Label1" runat="server" Text="Label"></asp:Label>
<br
/>
<asp:Label
ID="Label2" runat="server" Text="Label"></asp:Label>
<asp:Button
ID="Button1" runat="server" OnClick="Button1_Click" Text="Up1Button" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button
ID="Button4" runat="server" OnClick="Button4_Click" Text="ParentUpdatePanelButton" />
</ContentTemplate>
</asp:UpdatePanel>
As I mentioned above when we use nested updatepanels the
UpdateMode property behaves in the following way.
Ø
When parent panel UpdateMode is always and child panel are
conditional the parent panel properties are applicable to child updatepanel.
Ø
But when parent panel UpdateMode is conditional and Child
panel is always, the parent panel properties are not applicable.
Updating a control which is outside the panel
Let’s say we have a scenario where want to update a
control which is outside the updatepanel using the asynchronous postback of the
updatepanel. Normally we can update that using only the synchronous postback, we
can leverage the scriptmanager utilities on server and client run time to
achieve this using asynchronous postback. Now the requirement is I want to
update a label control value during the asynchronous postback of a button click,
just write the following in the button click event:
ScriptManager1.RegisterDataItem(lblOutside, "Satheesh Babu");
On the client side we need to write the following code
to update the label.
<script language="javascript">
var pageInstance =
Sys.WebForms.PageRequestManager.getInstance();
pageInstance.add_pageLoaded(UpdateLabelHandler);
function UpdateLabelHandler(sender, args)
{
var ControldataItems = args.get_dataItems();
if ($get('lblOutside') !== null)
$get('lblOutside').innerHTML = ControldataItems ['lblOutside'];
}
</script>
The label is updated now on the browser which is outside
the updatepanel. Just notice the markup rendered to the client when we register
a value on the server using scriptmanager.
HTTP/1.1 200 OK
Server:
Microsoft-IIS/5.1
Date: Sun, 30 Jan 2011
14:26:27 GMT
X-Powered-By:
ASP.NET
X-AspNet-Version:
2.0.50727
Transfer-Encoding:
chunked
Cache-Control:
private
Content-Type: text/plain;
charset=utf-8
40c
228|updatePanel|UpdatePanel1|
<span
id="Label1">Suresh Kumar</span>
<br
/>
<span
id="Label2">Label</span>
<input
type="submit" name="Button1" value="Up1Button" id="Button1" />
|108|updatePanel|UpdatePanel2|
<input
type="submit" name="UP2Button1" value="UP2Button1" id="UP2Button1"
/>
|132|hiddenField|__VIEWSTATE|/wEPDwUKLTMxOTgzNzM5OQ9kFgICAw9kFgICAw9kF
gJmD2QWAgIBD2QWAmYPZBYCAgEPDxYCHgRUZXh0BQxTdXJlc2ggS3VtYXJkZGRv5Dw1wZk9
AtGtJw1aKmXpQl2V7A==|96|hiddenField|__EVENTVALIDATION|/wEWCALRnKmOBwKM54
rGBgLghc/5DgKF2fXbAwKgwpPxDQLPhrqxDwLWlM+bAgK7q7GGCNejFt6c4/j1hjEen06zKEA
fTZ7F|0|asyncPostBackControlIDs|||0|postBackControlIDs|||69|updatePanelIDs
||tUpdatePanel3,tUpdatePanel1,tUpdatePanel4,tUpdatePanel5,tUpdatePanel2|0|
childUpdatePanelIDs|||25|panelsToRefreshIDs||UpdatePanel1,UpdatePanel2|2|
asyncPostBackTimeout||90|23|formAction||UpdatePanelSample1.aspx|
18|pageTitle||UpdatePanel
Sample|13|dataItem|lblOutside|Satheesh Babu|
0
Check the highlighted ones on the above response. They
are registered as dataitems on the server and we can use them on the client side
runtime using the PageRequestManager.
|