If you need to inject JavaScript into a page when performing an asynchronous postback, you need to take advantage of the methods exposed by the ScriptManager class.. The page in Listing
Trang 1Runat=”server” />
<asp:Button
id=”btnSearch”
Text=”Search”
OnClick=”btnSearch_Click”
Runat=”server” />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel
id=”upResults”
UpdateMode=”Conditional”
Runat=”server”>
<ContentTemplate>
Results Time: <%= DateTime.Now.ToString(“T”) %>
<br />
<asp:GridView
id=”grdResults”
runat=”server” />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
UpdatePanels and JavaScript
You must take special care when using JavaScript with UpdatePanel controls If you use
the standard methods of the ClientScriptManager class for working with JavaScript, they
will fail when called during an asynchronous request
For example, I often use the Page.ClientScript.RegisterStartupScript() method from
my server-side code to inject a JavaScript script into a page dynamically The page in
Listing 38.8 contains a Delete All Files button When you click the button, and the
FileHelper.DeleteAll() method returns true, a JavaScript alert box displays the message
All Files Deleted Successfully! (see Figure 38.7)
Trang 2LISTING 38.8 ShowAlert.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
protected void btnDeleteAll_Click(object sender, EventArgs e)
{
if (FileHelper.DeleteAll() == true)
{
string script = @”alert(‘All Files Deleted Successfully!’);”;
Page.ClientScript.RegisterStartupScript(this.GetType(), “filesDeleted”,
➥script, true);
}
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title>Show Alert</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Button
id=”btnDeleteAll”
Text=”Delete All Files”
OnClick=”btnDeleteAll_Click”
FIGURE 38.7 Displaying a JavaScript alert
Trang 3Runat=”server” />
</div>
</form>
</body>
</html>
Unfortunately, the page in Listing 38.8 does not work when the Button control is wrapped
in an UpdatePanel The JavaScript alert never appears after you click the button The page
fails silently
If you need to inject JavaScript into a page when performing an asynchronous postback,
you need to take advantage of the methods exposed by the ScriptManager class The
ScriptManager class duplicates all the standard JavaScript methods of the
ClientScriptManager class, including the following:
RegisterArrayDeclaration()—Enables you to add a JavaScript array to the page
RegisterClientScriptBlock()—Enables you to add an inline JavaScript script right
after the opening <form> tag
RegisterClientScriptInclude()—Enables you to add a JavaScript <script src=””>
tag to a page
RegisterClientScriptResource()—Enables you to add a reference to a JavaScript
file embedded in an assembly
RegisterExpandoAttribute()—Enables you to register a tag expando
RegisterOnSubmitStatement()—Enables you to register a JavaScript script that is
executed when the form is submitted
RegisterStartupScript()—Enables you to add an inline JavaScript script right
before the closing <form> tag
The page in Listing 38.9 demonstrates how you can add JavaScript from the server to a
page when performing an asynchronous postback
LISTING 38.9 ShowAlertUpdatePanel.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
protected void btnDeleteAll_Click(object sender, EventArgs e)
{
if (FileHelper.DeleteAll() == true)
{
Trang 4string script = @”alert(‘All Files Deleted Successfully!’);”;
ScriptManager.RegisterStartupScript(this, this.GetType(), “filesDeleted”,
➥script, true);
}
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head id=”Head1” runat=”server”>
<title>Show Alert UpdatePanel</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:ScriptManager
id=”sm1”
Runat=”server” />
<asp:UpdatePanel id=”up1” runat=”server”>
<ContentTemplate>
UpdatePanel Time: <%= DateTime.Now.ToString(“T”) %>
<br />
<asp:Button
id=”btnDeleteAll”
Text=”Delete All Files”
OnClick=”btnDeleteAll_Click”
Runat=”server” />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
In Listing 38.9, the Button control is wrapped in an UpdatePanel When you click the
button, the ScriptManager.RegisterStartupScript() method adds the JavaScript alert to
the page dynamically
UpdatePanel Server-Side Page Execution Life Cycle
You need to understand that a server-side page goes through its normal page execution life
cycle when you perform an asynchronous postback The Page PreInit, Init, Load, and
PreRender events are raised for an asynchronous postback in just the same way as these
events are raised for a normal postback
Trang 5The page in Listing 38.10 logs each server event and displays the log in a BulletedList
control (see Figure 38.8)
FIGURE 38.8 Viewing an asynchronous postback’s server lifecycle
LISTING 38.10 ServerLifecycle.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<script runat=”server”>
public ArrayList _log = new ArrayList();
void Page_PreInit()
{
_log.Add(“PreInit “ + sm1.IsInAsyncPostBack);
}
void Page_Init()
{
_log.Add(“Init “ + sm1.IsInAsyncPostBack);
}
void Page_Load()
{
_log.Add(“Load “ + sm1.IsInAsyncPostBack);
}
void Page_PreRender()
{
_log.Add(“PreRender “ + sm1.IsInAsyncPostBack);
// Show Lifecycle log
bltLog.DataSource = _log;
Trang 6bltLog.DataBind();
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title>Server Lifecycle</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:ScriptManager
id=”sm1”
runat=”server” />
<asp:UpdatePanel
id=”up1”
runat=”server”>
<ContentTemplate>
<asp:Button
id=”btnLog”
Text=”Show Server Page Lifecycle”
Runat=”server” />
<asp:BulletedList
id=”bltLog”
Runat=”server” />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
When you first open the page in Listing 38.10, each page event is listed in the
BulletedList control Next to each event, you see the word False The
ScriptManager.IsInAsyncPostBack property displays whether the page is processed within
a normal postback or an asynchronous postback
The page includes an UpdatePanel that contains a Button control Clicking the button
initiates an asynchronous postback After you click the button, the exact same list of
events appears in the BulletedList control The exact same events are raised during an
asynchronous postback as are raised during a normal postback
Trang 7NOTE
ScriptManager.IsInAsyncPostBack has the value False when the PreInit event is
raised during an asynchronous postback This IsInAsyncPostBack property is updated
after this event (So it is just wrong.)
UpdatePanel Client-Side Page Execution Life Cycle
A page that contains a ScriptManager control not only has a server-side page execution
life cycle, it also has a client-side page execution life cycle The following series of events
happen on the client-side:
Application.init—Raised when a page is first requested This event is not raised
during an asynchronous postback
PageRequestManager.initializeRequest—Raised before an asynchronous request to
the server starts
PageRequestManager.beginRequest—Raised before an asynchronous request to the
server starts
PageRequestManager.pageLoading—Raised after an asynchronous response is
received from the server but before UpdatePanel content is updated
PageRequestManager.pageLoaded—Raised after an asynchronous response is received
from the server and after UpdatePanel content is updated Also raised during the
initial page request
Application.load—Raised during both normal and asynchronous postbacks
PageRequestManager.endRequest—Raised after an asynchronous response both
when there is and when there isn’t an error
Application.unload—Raised before the user leaves or reloads the page
Two client-side objects raise client life-cycle events: Sys.Application object and
Sys.WebForms.PageRequestManager The Sys.Application events happen in a page
regard-less of whether the page contains UpdatePanel controls The
Sys.WebForms.PageRequestManager events are tied to UpdatePanels
The page in Listing 38.11 illustrates when each of these client-side events occurs The page
takes advantage of ASP.NET AJAX’s client-side trace support When each client event
occurs, Sys.Debug.trace() is used to write a message to the Trace Console Figure 38.9
shows the page after the Async Postback button is clicked
Trang 8LISTING 38.11 ClientLifecycle.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml”>
<head runat=”server”>
<title>Client Lifecycle</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:ScriptManager ID=”ScriptManager1” runat=”server” />
<asp:UpdatePanel ID=”up1” runat=”server”>
<ContentTemplate>
<asp:Button ID=”btnAsync” Text=”Async Postback” runat=”server” />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Button ID=”Button1” Text=”Normal Postback” runat=”server” />
<br /><br />
<textarea id=”TraceConsole” cols=”60” rows=”10”></textarea>
</div>
</form>
</body>
<script type=”text/javascript”>
Sys.Application.add_init(application_init);
FIGURE 38.9 Viewing an asynchronous page’s client execution lifecycle
Trang 9function application_init()
{
Sys.Debug.trace(“Application.Init”);
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest( prm_initializeRequest );
prm.add_beginRequest( prm_beginRequest );
prm.add_pageLoading( prm_pageLoading );
prm.add_pageLoaded( prm_pageLoaded );
prm.add_endRequest( prm_endRequest );
}
function pageLoad()
{
Sys.Debug.trace(“Application.Load”);
}
function prm_initializeRequest()
{
Sys.Debug.trace(“PageRequestManager.initializeRequest”);
}
function prm_beginRequest()
{
Sys.Debug.trace(“PageRequestManager.beginRequest”);
}
function prm_pageLoading()
{
Sys.Debug.trace(“PageRequestManager.pageLoading”);
}
function prm_pageLoaded()
{
Sys.Debug.trace(“PageRequestManager.pageLoaded”);
}
function prm_endRequest()
{
Sys.Debug.trace(“PageRequestManager.endRequest”);
}
function pageUnload()
{
alert(“Application.Unload”);
Trang 10}
</script>
</html>
Because we are discussing client-side events, we have moved over into the JavaScript
world The script in Listing 38.11 has to be written in JavaScript because it executes within
the browser and not on the server
Different information is available during each client-side event You can access the event
information by reading the properties of the second parameter passed to the event
handler What follows is the event information passed to each event handler
InitializeRequestEventArgs
Passed to the PageRequestManager.initializeRequest event handler Supports the
follow-ing properties:
cancel—Enables you to cancel the current asynchronous postback
postBackElement—The element that caused the asynchronous postback
request—The request object used to perform the asynchronous postback
BeginRequestEventArgs
Passed to the PageRequestManager.beginRequest event handler Supports the following
properties:
postBackElement—The element that caused the asynchronous postback
request—The request object used to perform the asynchronous postback
PageLoadingEventArgs
Passed to the PageRequestManager.pageLoading event handler Supports the following
properties:
dataItems—The data items registered with the ScriptManager.RegisterDataItem()
method
panelsDeleting—The array of UpdatePanel elements being deleted
panelsUpdating—The array of UpdatePanel elements being updated
PageLoadedEventArgs
Passed to the PageRequestManager.pageLoaded event handler Supports the following
properties:
dataItems—The data items registered with the ScriptManager.RegisterDataItem()
method
panelsCreated—The array of UpdatePanel elements created
panelsUpdated—The array of UpdatePanel elements updated