Tải bản đầy đủ (.pdf) (44 trang)

Beginning Web Development, Silverlight, and ASP.NET AJAX From Novice to Professional phần 8 ppsx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.75 MB, 44 trang )

<script yfwYKTfiMeq0vuB4l8z1TrL35xfv6g8XP_WrOPfTwL66AB2oz
8QRS5Lwfo666oDJgLW4Va2KNp_CEQC1pA2Sjb3Jm9uPm
6XGO-wEIVg6lRA1&amp;t=633062590837065070"
type="text/javascript"></script>
<script src="/ScriptResource.axd?d=
yfwYKTfiMeq0vuB4l8z1TrL35xfv6g8XP_WrOPfTwL66AB2oz
8QRS5Lwfo666oDJgLW4Va2KNp_CEQC1pA2SjaH2gXu3ERVLt
TRI4HEwCJk1&amp;t=633062590837065070"
type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
Sys.WebForms.PageRequestManager._initialize('ScriptManager1',
document.getElementById('form1'));
Sys.WebForms.PageRequestManager.getInstance()._updateControls([], [], [], 90);
//]]>
</script>
<div>
</div>
<script type="text/javascript">
<!
Sys.Application.initialize();
// >
</script>
</form>
</body>
</html>
There’s lots of new stuff here. You’ll be seeing how this all hangs together as you work
through this book, but for now consider the
<script> blocks referencing WebResource.axd
and ScriptResource.axd. These guys are downloading the various script libraries that the
browser needs for this page. Part of this is to support the core extensions to JavaScript,


adding object orientation so that calls like
Sys.Application.Initialize() make sense.
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET288
9594CH12.qxd 1/22/08 10:59 AM Page 288
Migrating ASP.NET to AJAX
One of the nicest things about ASP.NET AJAX is the fact that the UpdatePanel control
can be used to add AJAX functionality to an existing ASP.NET application. This is simply
achieved by wrapping the relevant controls with an UpdatePanel.
Consider the following example. Add a new web form to your application and call it
AddWithUpdatePanel.aspx. On this form, add a couple of text boxes, a button, and a label,
and call them txtA, txtB, btnAdd, and lblAns, respectively. The source of your page should
look like this:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="AddWIthUpdatePanel.aspx.cs"
Inherits="Example2.AddWIthUpdatePanel" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
" /><html xmlns=" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtA" runat="server"></asp:TextBox><br />
<asp:TextBox ID="txtB" runat="server"></asp:TextBox><br />
<br />
<asp:Button ID="btnAdd" runat="server" OnClick="btnAdd_Click"
Text="Add Em Up" /><br />
<asp:Label ID="lblAns" runat="server"></asp:Label><br />
<br />

&nbsp;</div>
</form>
</body>
</html>
Double-click the button to add an event handler, and add the following code to it:
protected void btnAdd_Click(object sender, EventArgs e)
{
int a = Convert.ToInt16(txtA.Text);
int b = Convert.ToInt16(txtB.Text);
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 289
9594CH12.qxd 1/22/08 10:59 AM Page 289
int c = a + b;
lblAns.Text = c.ToString();
}
Now when you run the application, you’ll see something like Figure 12-8. When you
type the numbers into the text fields, nothing happens until you click the button, which
triggers a postback and a full refresh of the page. Depending on your system speed, you
may or may not see a page blink, but you can notice the full page refresh by looking at the
status bar.
You can convert this to an Ajax application without changing any code. To do this,
drag and drop a ScriptManager control from the Toolbox onto the page. (Look back
to Figure 12-6 to see the Toolbox.) After doing this, drop an UpdatePanel on the page,
and then find the Panel control in the standard Toolbox and add a panel inside the
UpdatePanel. The Panel resolves to a
<div> at runtime, and can be resized within the
Designer, causing the UpdatePanel to match it.
See Figure 12-8 for an example.
Figure 12-8. U
pdating an ASP
.NET page to use A

jax
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET290
9594CH12.qxd 1/22/08 10:59 AM Page 290
For the next step, you should drag and drop the text boxes, button, and label into the
panel that you just added. Once you’ve done this, the source code of your page will look
something like this:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="AddWIthUpdatePanel.aspx.cs"
Inherits="Example2.AddWIthUpdatePanel" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
" /><html xmlns=" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<br />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Panel ID="Panel1" runat="server" Height="88px" Width="388px">
<asp:TextBox ID="txtA" runat="server"></asp:TextBox><br />
<asp:TextBox ID="txtB" runat="server"></asp:TextBox><br />
<asp:Button ID="btnAdd" runat="server" OnClick="btnAdd_Click"
Text="Add Em Up" /><br />
<asp:Label ID="lblAns" runat="server"></asp:Label></asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>

</div>
</form>
</body>
</html>
And that’s all you’ll need to do to get this application to become an Ajax one. Run the
application, and you’ll see that when you run it, it no longer performs a full page refresh;
it just does a partial Ajax-style one. You can see this in Figure 12-9.
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 291
9594CH12.qxd 1/22/08 10:59 AM Page 291
Figure 12-9. ASP.NET application using Ajax
Building a Simple Ajax Application with ASP.NET
Now, the example of adding two numbers is all very good, but how does ASP.NET AJAX
stack up when writing a more typical ASP.NET page—for example, one that uses a
DataGrid to bind to a back-end data source?
■Note If you are amending an existing ASP.NET application to use Ajax, you should remember that some
changes to your
Web.config file will need to be made to reference the AJAX libraries. A good shortcut is to
create a new ASP.NET AJAX application and copy the information from its Web.config file.
Let’s put this together now. First, create a new web form and add a SqlDataSource
control to it. Open the SqlDataSource Tasks pane, as shown in Figure 12-10.
Figure 12-10. Adding a SqlDataSource to an Ajax application
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET292
9594CH12.qxd 1/22/08 10:59 AM Page 292
Click the Configure Data Source link to go into the Configure Data Source wizard for
the SqlDataSource. To see all the steps in this wizard, take a look back at Chapter 4, where
the same connection is made. Otherwise, if you already have the AdventureWorks data-
base set up with SQL Server, enter the configuration string on the first step on the wizard.
See Figure 12-11 for details. Here’s an example connection string:
Data Source=.\SQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=True
Figure 12-11. Connecting to the database

When you click Next, you’ll be given the option to either use a custom SQL statement
or specify columns from a table or view (see Figure 12-12). Select the former (“Specify a
custom SQL statement or stored procedure”).
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 293
9594CH12.qxd 1/22/08 10:59 AM Page 293
Figure 12-12. Specifying the query type
When y
ou click Next, you’ll be taken to the Define Custom Statements or Stored
Procedures scr
een, as shown in Figure 12-13. Enter the following SQL:
SELECT AddressLine1, PostalCode FROM Person.Address WHERE (PostalCode = @PostalCode)
This selects the first line of the customer

s addr
ess and their ZIP code when the ZIP
code matches a par
ameterized value. You’ll see how to set the default value in the next
step
.
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET294
9594CH12.qxd 1/22/08 10:59 AM Page 294
Figure 12-13. Setting up the SQL query
When you click Next, you’ll be taken to the Define Parameters step (see Figure 12-14).
Here you can set up default parameter values that will be used in your SQL query. Select
QueryS
tring as the parameter source, and the wizard will set up the code required to read
the par
ameter fr
om the URI that you use to call the service. Give the query string field a
name (i.e., ZIP) and a default value. Now if you call your service using a URI like

http://
server/pagename.aspx?ZIP=12345, the @PostalCode parameter will be loaded with 12345
prior to calling the database.
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 295
9594CH12.qxd 1/22/08 10:59 AM Page 295
Figure 12-14. Defining the parameters
After this, you can finish out the wizard, and you’ll have a configured data source.
The wizard has added some markup to your page to instruct the server at runtime to
connect to the data and run the query, using the query string parameter that you defined.
It should look something like this:
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString=
"<%$ ConnectionStrings:AdventureWorksConnectionString %>"
SelectCommand="SELECT AddressLine1, PostalCode FROM Person.Address
WHERE (PostalCode = @PostalCode)">
<SelectParameters>
<asp:QueryStringParameter DefaultValue="90210"
Name="PostalCode" QueryStringField="ZIP" />
</SelectParameters>
</asp:SqlDataSource>
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET296
9594CH12.qxd 1/22/08 10:59 AM Page 296
Now that you have your data connection, it’s pretty easy to tie a DataGrid up to it to
view the results of the query.
Drag and drop a GridView control onto the page, and open its Tasks pane (see
Figure 12-15 for details).
Figure 12-15. Adding a GridView to your application
Select SqlDataSource1 from the Choose Data Source drop-down, and you’ll see the
grid reconfigure itself to the fields that the data source exposes. Enable paging, sorting,
and selection by selecting their check boxes in the Tasks pane, as shown in Figure 12-16.

Figure 12-16. B
inding the grid to the data sour
ce
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 297
9594CH12.qxd 1/22/08 10:59 AM Page 297
Run the application. You’ll see that you can select different pages on the grid, select
items on the grid, and sort the items by clicking the column headers. However, every time
you do this, you’ll see a postback to the server and a page blink (see Figure 12-17). Notice
the status bar progress at the bottom-left-hand side!
Figure 12-17. Running the data-bound application
Now let’s see how easy it is to turn this into an Ajax application. As with everything
else in ASP.NET AJAX, the first thing you should do is add a
ScriptManager object to the
design sur
face
.
O
nce y
ou hav
e this
, add an
U
pdateP
anel. D
rag the DataGrid onto the design surface
for the U
pdateP
anel (see F
igur
e 12-18).

CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET298
9594CH12.qxd 1/22/08 10:59 AM Page 298
Figure 12-18. Adding a ScriptManager and an UpdatePanel
Now when you run your application, it will be an Ajax one, and you will not see the
full page refresh when you perform an action on the DataGrid. For your reference, here is
the full HTML markup for the page. Despite the pretty complex functionality, no C# or
JavaScript coding was required.
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default2.aspx.cs" Inherits="Default2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
" /><html xmlns=" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 299
9594CH12.qxd 1/22/08 10:59 AM Page 299
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString %>"
SelectCommand="SELECT AddressLine1, PostalCode FROM
Person.Address WHERE (PostalCode = @PostalCode)">
<SelectParameters>
<asp:QueryStringParameter DefaultValue="90210"
Name="PostalCode"
QueryStringField="ZIP" />
</SelectParameters>

</asp:SqlDataSource>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="GridView1"
runat="server"
AllowPaging="True"
AllowSorting="True"
AutoGenerateColumns="False"
DataSourceID="SqlDataSource1">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="AddressLine1"
HeaderText="AddressLine1"
SortExpression="AddressLine1" />
<asp:BoundField DataField="PostalCode"
HeaderText="PostalCode"
SortExpression="PostalCode" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
Using Ajax with Web Services
S
ome other
useful technologies that come with the ASP.NET AJAX extensions are the abil-
ity to dev

elop a web service that provides a JavaScript proxy, and client-side libraries that
allo
w you to reference and use this proxy directly from the browser. This is very useful for
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET300
9594CH12.qxd 1/22/08 10:59 AM Page 300
developing mashup-style applications, where an interim server is not necessary to con-
sume the web service and provide the data in HTML format, as is the typical design
pattern when using web services. In this section, you’ll build a web service, make it
accessible to JavaScript, and build a simple client that accesses it.
For this example, you will build a web service that fronts the AdventureWorks data-
base and uses its country code lookup table to allow you to convert a country code into a
country name. For example, WS evaluates to Samoa and GL to Greenland. You can see
this data in the Person.CountryRegion table.
If you haven’t already set up an AdventureWorks database and connection to it in
your application, it’s a good idea to work through Chapters 4 and 5 and the samples
earlier in this chapter before continuing. You can still use this sample, but if you have
connectivity trouble (i.e., reading the connection string from
Web.config), go through
those earlier samples and y
ou should be fine.
To get started, add a new ASMX web ser
vice to your solution and call it
DataService.
asmx. The full code for this service is listed following. This implements the simple web
method
GetCountryForRegion, taking in the region code and returning the country that
matches it.
using System;
using System.Web;
using System.Collections;

using System.Web.Services;
using System.Web.Services.Protocols;
using System.Data;
using System.Data.SqlClient;
using System.Web.Configuration;
[WebService(Namespace = " />[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class DataService : System.Web.Services.WebService {
public DataService () {
//Uncomment the following line if using designed components
//InitializeComponent();
}
[WebMethod]
public string GetCountryForRegion(string strRegion)
{
string strReturn = "";
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 301
9594CH12.qxd 1/22/08 10:59 AM Page 301
string connectionString = WebConfigurationManager.ConnectionStrings
["AdventureWorksConnectionString"].ConnectionString;
SqlConnection sqlCon = new SqlConnection(connectionString);
SqlCommand sqlComm = new SqlCommand();
sqlComm.Connection = sqlCon;
sqlComm.CommandType = CommandType.Text;
sqlComm.CommandText =
"SELECT * FROM Person.CountryRegion WHERE (CountryRegionCode = @strCRC)";
sqlComm.Parameters.Add("@strCRC", strRegion);
sqlCon.Open();
SqlDataReader sRead = sqlComm.ExecuteReader();
while (sRead.Read())
{

strReturn = sRead["Name"].ToString();
}
sqlCon.Close();
return strReturn;
}
}
For this web service to be consumed from JavaScript, it has to be a script service. This
is a new attribute that has been added by the ASP.NET AJAX extensions.
To use scriptable services, you should first add a reference to them at the top of your
service. It will look like this:
using System.Web.Script.Services;
Next, you’ll attribute your service as a script service by putting the [ScriptService]
attr
ibute on the class declaration.
Y
our service is now ready to produce JavaScript proxies that can be consumed within
the br
o
wser
.
You can test this by calling your service, and then appending
/js to the URL.
I
f y
our ser
vice is successfully set up
, it will generate a
.js file that the br
o
wser will do

wn
-
load (see F
igur
e 12-19).
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET302
9594CH12.qxd 1/22/08 10:59 AM Page 302
Figure 12-19. Accessing the JavaScript proxy
This proxy file will look something like this:
var DataService=function() {
DataService.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
DataService.prototype={
GetCountryForRegion:function(
strRegion,succeededCallback, failedCallback, userContext)
{
return this._invoke(DataService.get_path(),
'GetCountryForRegion',false,{strRegion:strRegion},
succeededCallback,failedCallback,userContext); }}
DataService.registerClass('DataService',Sys.Net.WebServiceProxy);
DataService._staticInstance = new DataService();
DataService.set_path = function(value)
{ DataService._staticInstance._path = value; }
DataService.get_path = function()
{ return DataService._staticInstance._path; }
DataService.set_timeout = function(value)

{ DataService._staticInstance._timeout = value; }
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 303
9594CH12.qxd 1/22/08 10:59 AM Page 303
DataService.get_timeout = function()
{ return DataService._staticInstance._timeout; }
DataService.set_defaultUserContext = function(value)
{ DataService._staticInstance._userContext = value; }
DataService.get_defaultUserContext = function()
{ return DataService._staticInstance._userContext; }
DataService.set_defaultSucceededCallback = function(value)
{ DataService._staticInstance._succeeded = value; }
DataService.get_defaultSucceededCallback = function()
{ return DataService._staticInstance._succeeded; }
DataService.set_defaultFailedCallback = function(value)
{ DataService._staticInstance._failed = value; }
DataService.get_defaultFailedCallback = function()
{ return DataService._staticInstance._failed; }
DataService.set_path("/Example3/DataService.asmx");
DataService.GetCountryForRegion=
function(strRegion,onSuccess,onFailed,userContext)
{DataService._staticInstance.GetCountryForRegion(strRegion,
onSuccess,onFailed,userContext); }
This is pure JavaScript that has dependencies on the ASP.NET AJAX JavaScript
librar
ies, so to use this service in a client, you’ll have to make sure that the libraries are
present. If you use ASP.NET to deliver the client page, then they are downloaded auto-
matically when you use the
<ScriptManager> component; otherwise you will have to
deliver the libraries yourself through an HTML
<script> reference. The libraries are freely

downloadable from
/>The next step is to build a page that consumes this web service. To do this, add a new
ASPX page to your solution, and call it
CountryCode.aspx.
Add a ScriptManager component to
CountryCode.aspx. Take a look at its Services
property, and you’ll see an ellipsis button that opens the ServiceReference Collection
Editor. Use this to add a service reference to the DataService that you just set up (see
Figure 12-20).
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET304
9594CH12.qxd 1/22/08 10:59 AM Page 304
Figure 12-20. Adding a service reference
This will generate markup that looks like this:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="DataService.asmx" />
</Services>
</asp:ScriptManager>
Next, add some HTML markup for an input text box and an input button. Double-
click the button, and a JavaScript event handler will be created. Finally, add a
<div> to
your page and call it CC.
Your page markup will look like this:
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="CountryCode.aspx.cs" Inherits="CountryCode" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
" />CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 305
9594CH12.qxd 1/22/08 10:59 AM Page 305
<html xmlns=" >
<head runat="server">

<title>Untitled Page</title>
<script language="javascript" type="text/javascript">
// <!CDATA[
function btnLookup_onclick() {
}
// ]]>
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="DataService.asmx" />
</Services>
</asp:ScriptManager>
<br />
Enter Country Code
<input id="txtCC" type="text" /><br />
<br />
<input id="btnLookup" type="button"
value="Look Up" onclick="return btnLookup_onclick()" /><br />
<br />
<div id="CC"></div>
</div>
</form>
</body>
</html>
The next step is to add the JavaScript code that calls the web service when you click
the button. The ScriptManager service reference handles the downloading of the proxy,

so you’ll have a class called
DataService available to you. So, to call the GetCountryForRegion
method using JavaScript, you just call it, specifying the parameter to pass and the call-
backs for successful completion and timeout. Your call (with a hard-coded parameter)
should look like this:
DataService.GetCountryForRegion(strCC, onReturn, onTimeOut);
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET306
9594CH12.qxd 1/22/08 10:59 AM Page 306
Thus, to use the text box value to call the web service, you would use the button click
event handler that was created earlier:
function btnLookup_onclick() {
var strCC = document.all("txtCC").value;;
DataService.GetCountryForRegion(strCC, onReturn, onTimeOut);
}
In JavaScript, you use document.all to look up an HTML control, pass it the ID of the
control, and query its properties. So, the first line in this JavaScript takes the value of the
text box and loads it into the
strCC var.
Now all that remains is to implement the
onReturn and onTimeOut functions. These are
standard JavaScript functions that take a
result parameter. You can see them here:
function onReturn(result)
{
CC.innerHTML = result;
}
function onTimeOut(result)
{
alert("You hit a timeout!");
}

The result that a successful call to the web service r
eturns is a string, so you can set
the
innerHTML of the <div> to this result and it will appear on the page. And that’s it—you
now have a pure thin-client web application that directly consumes a web service via
JavaScript-based proxies!
You can see this application in action in Figure 12-21.
Figure 12-21. Running the JavaScript service client
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET 307
9594CH12.qxd 1/22/08 10:59 AM Page 307
Summary
In this chapter, you were introduced to the ASP.NET extensions that allow you to build
AJAX applications easily using your familiar tools and skills. These extensions make Ajax
applications a lot easier to write, as in many cases they emit the requisite Ajax code on
your behalf, without you needing to explicitly code against the
XMLHttpRequest API. You
took a look at some examples of building new Ajax applications using Visual Studio, as
well as how straightforward it is to amend
existing ASP.NET applications for a better user
experience using these tools. Finally, you looked at one of the more useful facets of
ASP.NET AJAX—the facility to build a web service that exposes a JavaScript proxy, and
how to consume this proxy, allowing web services to be called directly from the browser!
CHAPTER 12 ■ AJAX EXTENSIONS FOR ASP.NET308
9594CH12.qxd 1/22/08 10:59 AM Page 308
Ajax Scripts and Services
As you saw in Chapter 12, ASP.NET AJAX has both server and client components. You
saw how you use the ScriptManager to create a service reference so that a web service
can be accessed directly from JavaScript.
In this chapter, you will look at some of the server controls and their supporting
classes in some more detail. In particular, you will look at the ScriptManager control and

how it can be used to link your server and client applications neatly. It enables ASP.NET
AJAX applications to work within the browser, along with its partner control, the Script-
ManagerProxy. You’ll see how to deliver custom scripts to the browser, how to manage
partial page rendering, and how to access web services directly from script.
You’ll build on this to look at how Ajax applications can access ASP.NET services such
as memberships and profiles, building out a role-based secured site in ASP.NET and then
seeing how this can be accessed from JavaScript as well as ASP.NET.
The ScriptManager Class
The ScriptManager class is designed to manage the ASP.NET AJAX script libraries, all the
script files that you use within your application, and proxy class generation for web serv-
ices. In addition, it supports the UpdatePanel, UpdateProgress, and Timer controls to
perform their partial page refreshing and timing functions. These controls will not work
unless a ScriptManager is present. Finally, it offers the JavaScript classes that are neces-
sary to access authentication and profiling services.
Par
tial Page R
endering
As you saw in the previous chapter, by storing page content and controls within Update-
Panels, partial page updates become possible. This is managed by the ScriptManager
component, which delivers scripts that interact with the page life cycle (you can see this
in more depth in Chapter 3). The ScriptManager has an
EnablePartialRendering property
that allows you to override this. By default, it is set to
true, meaning that partial rendering
is automatically enabled, and all UpdatePanel controls will refresh upon postback (but
309
CHAPTER 13
9594CH13.qxd 2/7/08 9:42 AM Page 309
not the whole page). Should you set it to false, then full page refreshes will occur on
postbacks, unless you write JavaScript code that uses the

XMLHttpRequest class to perform
asynchronous postbacks and then manually update the page. Typically for Ajax pages,
you will always set this to
true. If your page is going to be relatively static (i.e., no post-
backs to the server), and you want to use a ScriptManager to deliver JavaScript, then you
can set it to
false to reduce overhead.
Handling Errors in Partial Page Updates
In case you hit an error in the process of a partial page update, the ScriptManager has a
property called
AllowCustomErrorsRedirect (defaulting to true), which determines that
the custom errors section of the
Web.config file should be used when an error occurs—
namely that you can redirect the user to a friendly landing page instead of crashing them
out of your app.
Alternatively, you can catch and handle the
AsyncPostBackError event, and/or set
the
AsyncPostBackErrorMessage property to manage errors. To do this, you define the
AsyncPostBackError callback by setting the OnAsyncPostBackError attribute on the Script-
Manager control. Here’s an example:
<asp:ScriptManager ID="ScriptManager1" runat="server"
OnAsyncPostBackError="ScriptManager1_AsyncPostBackError">
</asp:ScriptManager>
Then, in your server code, you can implement a function that handles this error. In
this case, it takes the exception message and loads it into the
AsyncPostBackErrorMessage
property
, which is accessible from client-side script via the PageRequestManager (you’ll
see more of this in the next chapter).

protected void ScriptManager1_AsyncPostBackError(object sender,
AsyncPostBackErrorEventArgs e)
{
ScriptManager1.AsyncPostBackErrorMessage = e.Exception.Message;
}
For example, if you add an EndRequestHandler callback to the PageRequestManager,
like this:
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
you can then access the AsyncPostBackErrorMessage from your JavaScript code as part of
the
args sent back to the EndRequestHandler:
CHAPTER 13 ■ AJAX SCRIPTS AND SERVICES310
9594CH13.qxd 2/7/08 9:42 AM Page 310
function EndRequestHandler(sender, args)
{
var errorMessage = args.get_error().message;
alert(errorMessage);
}
Managing Custom Scripts
The typical way to add new scripts to a page is to use the <script> tag within HTML.
However, if your script library is using Ajax features, this is not always reliable. First, if the
browser accesses this script prior to reading the Ajax script libraries, it will hit parsing
errors. Second, if the script is accessing some of the security features of the Ajax library
(such as accessing profile information), it will fail. To get around these drawbacks in your
custom script, you can use the ScriptManager to deliver it for you.
Suppose, for example, you have a script like this, which uses the object-oriented
extensions of JavaScript that ASP.NET AJAX offers:
Type.registerNamespace("WebNext");
WebNext.House = function(streetName, townName, zipCode) {
this._streetName = streetName;

this._townName = townName;
this._zipCode = zipCode;
}
WebNext.House.prototype = {
getStreetName: function() {
return this._streetName;
},
getTownName: function() {
return this._townName;
},
getAddress: function() {
return this._streetName + ' ' + this._townName + ' ' + this._zipCode;
},
dispose: function() {
alert('removed ' + this.getAddress());
CHAPTER 13 ■ AJAX SCRIPTS AND SERVICES 311
9594CH13.qxd 2/7/08 9:42 AM Page 311
}
}
WebNext.House.registerClass('WebNext.House', null, Sys.IDisposable);
if (typeof(Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
You can then ensure that it is correctly and cleanly delivered to the browser by
declaring it as a script that the ScriptManager component will manage for you. Here’s
the markup to achieve this:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="House.js" />
</Scripts>
</asp:ScriptManager>
Using Web Services fr

om Script
A very powerful facet of the ScriptManager is that it allows you to declare references to
web services. If these services are attributed as scriptable, and thus generate a JavaScript
proxy, the ScriptManager can then initialize everything that is needed for a client to com-
municate directly with the service.
For example, consider the following simple web service. Note that it has been attrib-
uted as a
[ScriptService]. In order to do this, you’ll need to add a using reference to the
System.Web.Script.Services namespace.
<%@ WebService Language="C#" Class="SimpleService" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Script.Services;
[WebService(Namespace = " />[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class SimpleService : System.Web.Services.WebService {
[WebMethod]
public int AddEm(int x, int y) {
CHAPTER 13 ■ AJAX SCRIPTS AND SERVICES312
9594CH13.qxd 2/7/08 9:42 AM Page 312

×