The ASP.NET team is delivering a framework for generating Web
applications that can take advantage of the latest capabilities
in client functionality that fall under the general banner of
Asynchronous JavaScript and XML (AJAX) and Rich Interactive
Applications (RIA). The new Microsoft ASP.NET AJAX addition to
the .NET Framework includes a suite of JavaScript libraries (the
Client Framework or Client FX) that are the foundation for
creating rich behaviors and control-like functionality in the
browser. ASP.NET AJAX also includes a set of a server controls
and base classes for extender controls (the Server Framework or
Server FX) that provides AJAX programming functionality and
experiences for ASP.NET Web developers.
ASP.NET AJAX functionality has been available to the public
since October 2005 as a series of Community Technology Previews
(CTPs), demonstrating everything from rich client behavior and
asynchronous Web page postbacks to invoking and consuming Web
services through JavaScript proxies.
This paper describes the major differences between the final
CTP release (made publicly available in July 2006) and the
upcoming Microsoft ASP.NET AJAX v1.0 release (here called the RTM
release). It also discusses a "futures" preview version (the
Futures release) that adds functionality to the RTM release. (The
RTM and the Futures releases together enable the full
functionality and customer scenarios that were supported in the
early CTP releases.) Further changes to the RTM and Futures
releases may occur up to the Release Candidate (RC) version,
which will be the final release before RTM.
The document is organized in sections detailing specific
functionality in the CTP release and how the same functionality
is achieved with the RTM release. For each change there is a
description of the reasons behind the change along with some
technical insights.
This document includes example code for features included in
the previous CTPs as well as features to be packaged in the core
and Futures components in the RTM release. The following colors
are used in the code examples to provide clarity and allow quick
differentiation:
CTP release: Green
RTM release: Red
Futures release: Blue
First, thank you for the great feedback and real-world usage
data we have received during the pre-release stage of Microsoft
ASP.NET AJAX! The differences between the Community Technology
Preview (CTP) and the final RTM release of the Microsoft ASP.NET
AJAX have been made with the following primary goals in mind:
- Customer feedback -- We have made many changes based
on community forums discussions and feedback from early
adopters building Web applications using the CTP releases.
- Developer productivity -- We want to provide
extensive tool support in future releases of Visual Studio such
as script authoring, script debugging, and client error
handling and reporting. In addition, we want to improve the
programming model with clear patterns and consistency with the
.NET Framework design guidelines and principles where
applicable.
- Performance -- We want to reduce load time and the
size of the working set of scripts in the browser for both
release and debug scenarios. The amount of script and therefore
the memory consumed by object instances were factors in our
decisions.
The table below summarizes the goals we have for different
audience segments in providing a client-based JavaScript
framework (Client FX) and an ASP.NET server-based framework
(Server FX). Both frameworks are designed to be extensible in the
future. For example, the Client FX is designed so that it meets
our performance goals for today and can be used by server-based
controls such as AutoCompleteExtender, which is located
in the ASP.NET AJAX Control Toolkit, but it also includes
hooks for adding xml-script support and bindings in a future
release.
Note Tool and design-time improvements described in
this document are potentially targeted for the next release of
Visual Studio code-named “Orcas.”
| Audience |
Goals |
Notes |
| ASP.NET page developer creating server-based
pages |
- Incrementally update existing Web applications with
rich client functionality.
- Use familiar, consistent ASP.NET programming models
and tools.
- Reduce or eliminate the need to know or learn
JavaScript.
- Reduce or eliminate the need to write
browser-specific code.
- Leverage ASP.NET and .NET Framework programming
skills.
|
Developers utilize server controls that hide
JavaScript, but provide the richness demanded by
today’s Web application developers. |
| ASP.NET page developer creating client-based
pages |
- Define Client FX features to simplify creation and
use of client components.
- Provide a productive programming experience, such as
possible IntelliSense support in Visual Studio
“Orcas”.
- Reduce or eliminate the need to write
browser-specific script.
|
Page developers who want to create pure,
client-based pages independent of server technology require a
Client FX that enables simplicity for tasks such as creating
client objects and hooking events in a browser-independent
manner. |
| ASP.NET component developer |
- Provide a framework that enables the component
developer to create rich client functionality and
behaviors for ASP.NET server controls.
- Demonstrate patterns and concepts for creating
components that can support debug and release
deployments.
|
The Client FX handles browser detection and includes
extensibility. These specific features, along with the
broader Client FX and Server FX, provide component
developers the building blocks for creating script-rich
controls.
The primary goal for this audience is to provide a
foundation for a vibrant third-party component
community.
|
Overview of Major Changes
The following tables provide a summary of the major
differences between the CTP, RTM, and Futures releases. The
feature areas are split into client and server groups, with
information about sub-feature sets and the impact to the
consuming audience.
| Feature |
Change Made & Purpose |
Effect |
| Client FX |
| Client type system |
Changed from using closures to using prototypes.
Purpose:
- Improve overall performance and memory consumption of
object instances.
- Design for future possible IntelliSense support in
Visual Studio "Orcas".
- Provide better-defined design patterns.
|
Component developers and page developers can now use a
consistent model when creating types on the Client FX.
Page developers consuming such types should see small
code changes in addition to the increased productivity of
possible future IntelliSense and better debugging support
in Visual Studio.
|
| Client events |
Changed the model for attaching to a DOM event and for
exposing component events.
Purpose:
- Support a standard model and future
extensibility.
- Provide patterns similar to the .NET Framework.
|
Component developers and page developers can follow a
simple, familiar pattern for defining and attaching events.
Page developers attaching events will find new APIs
easier to follow.
|
| Client compatibility layer |
Compatibility is supported through browser detection and
browser capability and occurs completely on the client.
Purpose:
- Support standards-based model.
- Simplify browser-detection APIs.
|
Component developers and page developers can
leverage new APIs to help simplify multi-browser
targeting. |
| Client JavaScript extensions |
API changes.
Purpose:
- Avoid conflicts and compatibility issues with other
AJAX libraries and frameworks.
|
Page developers and component developers have
new API signatures to avoid collisions with other APIs. |
| Client "classes" and other types |
Changed the model for defining a class to be
prototype-based. Also changed the registration APIs to be
sealed; in addition, abstract classes are no longer
defined. Provided new enhancements to error handling
semantics.
Purpose:
- Faster object instantiation.
- Improved overall performance and memory consumption
of object instances.
|
Component developers obtain new models for defining custom
types.
Page developers obtain new aliases to instantiate types,
which eliminates previous complexity.
|
| Debug and release scripts |
Defined an optional model for specifying debug and release
versions of client scripts that can be independent of
server debug settings.
Page developers always reference the release script in
the ScriptManager control and can specify debug mode
separately for server and client code execution. Server
administrators can specify the deployment mode
configuration setting to ensure release scripts are used in
production.
Purpose:
- Possible tool support in Visual Studio
“Orcas” for debug versions of scripts;
scripts can also be leveraged by third parties.
- Provide page developers access to highly optimized
release scripts for production.
|
Component developers can optionally provide separate debug
and release versions of their own scripts.
Page developers have network-optimized scripts and
scripts that support debugging and possible future
IntelliSense in Visual Studio “Orcas”.
|
| Client Component, Behavior, and
Control types |
Removed bindings and actions. These types are defined in
the Futures release. The RTM release is designed in a way
for these to be layered in.
Several APIs moved from these classes to the new
DomElement class.
Purpose:
- Client FX simplification.
- APIs can now be used without first needing to
instantiate an object.
- Reduction in script size improves load times and
performance.
|
Component developers and page developers who
consume these types need to modify their API calls. |
| Client networking |
Created a simplified and more flexible design for calling
Web service methods from script.
Added support for providing default callback functions
and for passing a method name to the callback function.
Replaced the instance page method in the CTP release
with static page method support.
Removed support for calling WCF Web services (.svc
files) from script.
Removed the iframe executor class, which allowed
cross-domain calls.
Removed the following features from the CTP release:
- Assembly-based method calls.
- InitialData control.
- Batching Web service calls.
Purpose:
- Simplify Web service calls from script.
- Prepare for improved WCF implementation and
integration planned for release with Visual Studio
“Orcas.”
- Eliminate potential security holes with cross-domain
calls.
- Remove features not being used from the Client FX to
reduce size and improve performance.
- Reduce script size to improve load times and
performance.
|
Page developers have simplified and more flexible ways to
perform networking tasks.
Developers must remove references to WCF (.svc) Web
services, the iframe executor, and other features
removed from the Client FX.
|
| Client application services |
Provided a simplified and more flexible design for using
the Membership and Profile services from script; this is
aligned with the improvements in client networking for
calling Web service methods from script.
Added support for specifying default callback
functions.
Provided an additional Futures release implementation of
Profile service as a component, aligned with the previous
CTP release version.
Purpose: Simplify ASP.NET application services access
from script.
|
Page developers can use ASP.NET application
services more easily. |
| Futures Release: Client high-level
components, xml-script, client data, and type
descriptors |
Sys.* features have been moved to a new namespace
Sys.Preview.*.
Added support in the Client FX for a model to define a
simple type descriptor that can be consumed in the Futures
release.
The Futures release continues to support xml-script and
includes the following improvements:
- Bindings support unlimited nesting in components.
- Better namespace-to-component tag prefix
assignments.
Purpose: Refactor core Client FX for the RTM
release.
|
Page developers who use xml-script need to change their
code.
Changes may be required where properties are moved from
core objects in the RTM release to the Futures package.
Component developers can write components using the RTM
release that can also be used with Futures features.
|
| Feature |
Change Made & Purpose |
Effect |
| Server FX |
| ScriptManager control |
Changed the ScriptManager control to support new
UpdatePanel control features, such as registration
of scripts and style sheets. The error template has also
been removed.
Added new handling and features to ScriptManager
for referencing static scripts and Web resource-based
scripts, and introduced a new event to enable custom script
location resolution.
Improved ScriptManager for debug and
release script handling so it no longer infers debug status
solely from the server configuration setting.
Controls are now required to register their
resources with the ScriptManager control.
Purpose: Incorporate customer feedback and suggestions
for giving page developers more control and flexibility in
script handling and UpdatePanel usability.
|
Page developers obtain fine-grained control over script
handling.
Component developers must register their component
scripts and resources with the ScriptManager
control.
|
| ExtenderControl control |
The extender model was simplified to enable support for
one-control-to-many-extenders scenarios.
Changed the model for defining and registering a
controls’ client “library” and "instance"
script at run time to reduce the amount of page life-cycle
knowledge required. The new model supports reduced
JSON-style object creation or some future model.
Added support for possible design-time improvements in
Orcas for extenders to define their target control
types.
|
Component developers obtain simplified models for creating
extenders.
Page developers obtain improved and simplified extender
markup syntax.
|
| UpdatePanel control |
Made changes to ensure that the partial-page update model
works in all known conditions. This means:
- Controls must register their resources (scripts,
style sheets, etc.) through the ScriptManager
control.
- UpdatePanel no longer attempts to recognize
changes in the entire document; instead, it monitors
changes only within its content template.
Events have been added to the client
PageRequestManager control to enable more scenarios
related to asynchronous postbacks, such as animation
effects and progress controls.
UpdatePanel controls can now be added to a page both
dynamically and declaratively.
The trigger model has been improved by removing property
triggers and adding postback triggers to allow full
(synchronous) postbacks to be forced from within the
UpdatePanel control.
Purpose: Incorporate customer feedback and suggestions
for giving component developers and page developers more
flexibility and options for controlling partial-page
updates and full postbacks.
|
Component developers must use registration models.
Page developers obtain new handling and logical models
for the UpdatePanel control.
|
| Tag prefix for server controls |
Changed the tag prefix for ASP.NET AJAX controls from
<atlas:> to <asp:>.
Purpose: Normalize the namespace for declarative
controls to be consistent with other ASP.NET controls.
|
Developers with pages that include
declarative controls must globally change the control tag
prefix. |
| Futures release: Server
components |
Microsoft.Web.* features have been moved to a new
namespace Microsoft.Web.Preview.*.
Purpose: Refactor core Server FX for the RTM
release.
|
Changes may be required where properties are moved from
core objects in the RTM release to the Futures package.
Component developers can write components using the RTM
release that can also be used with Futures features.
|
Summary of Changes from Beta to Beta 2
A number of bug fixes and feature additions were made between
the Beta and Beta 2 releases of the ASP.NET AJAX 1.0 RTM. In this
section we describe the differences in general terms. Later
sections of this document describe the changes in more
detail.
Note : the following breaking changes have been made
from Beta to Beta 2:
- A new ScriptResource.axd handler has been added that
requires an entry in the Web.config file.
- Array.prototype extensions have been moved to static
APIs on the Array object.
- The ExtenderControl, IExtenderControl, and
IScriptControl types must register themselves with the
ScriptManager control in their PreRender
method.
- The Sys.UI.Key enumerations "return" and "delete"
have been renamed to "enter" and "del".
- The Sys.Services.AuthenticationService.logout method
now always redirects on successful completion. Previously a
redirect occurred only if you specified a URL. (If no URL is
specified, the page redirects to itself.)
- The Sys.Services.AuthenticationService.login and
logout methods both call the completed callback function
even if a redirect is about to occur. Previously, the callbacks
were skipped.
- Multiple DOM events can be created with the
$addHandlers and $clearHandlers aliases.
- Array.prototype extensions have been moved to static
APIs on the Array object.
- Sys.UI.Control APIs now include addCssClass,
removeCssClass, and toggleCssClass.
- The Sys.UI.Key enumerations return and
delete have been renamed to enter and
del
- The new Date, Number, and String
format and localeFormat methods use the
Sys.CultureInfo.InvariantCulture and
Sys.CultureInfo.CurrentCulture types.
- Enum.parse supports a new case-insensitivity
parameter.
- The debug.trace and debug.dump APIs have been
added.
- Events have been added to the Sys.Application class
for script loading exceptions.
- The Sys.Services.AuthenticationService.logout method
now always redirects on successful completion. Previously a
redirect occurred only if you specified a URL. (If no URL is
specified, the page redirects to itself.)
- The Sys.Services.AuthenticationService.login and
logout methods both call the completed callback function
even if a redirect is about to occur. Previously, the callbacks
were skipped.
'Sys' is undefined.
- The ExtenderControl, IScriptControl, and
IExtenderControl types must register with the
ScriptManager control during their PreRender
phase. The new model supports these types in more complex
scenarios such as within templates in data-bound controls.
- The ScriptManager control now includes the
following:
- New properties for globalization and localization
support.
- New APIs for supporting client focus with the
UpdatePanel control's partial-page rendering.
- A SupportsPartialRendering property that is
based on browser capabilities.
- A RegisterDispose method that can be used to
track objects for disposal during partial rendering so that
the object does not require a DOM element.
- Globalization support through the generation of a
client Sys.UI.CurrentCulture object that is
determined from the server’s thread culture. By
default, this value is determined based on the ACCEPT_LANG
header in the browser request.
- A ScriptLoadTimeout property for handling
scripts in the client.
Summary of Changes from Beta 2 to RC
This section summarizes bug fixes and feature additions that
were made between the Beta2 and RC releases of ASP.NET AJAX 1.0.
Later sections of this document describe the changes in more
detail.
The following are breaking changes:
- The core assembly has been changed from
Microsoft.Web.Extensions to System.Web.Extensions
so that applications built with the RTM release will be
compatible with the Orcas release. In your existing
applications, you must do the following:
- Ensure that your applications reference the new
assembly, and remove references to
Microsoft.Web.Extensions.
- Ensure that your Web.config files now references the
new assembly in all type references.
- Ensure that Microsoft.Web.Extensions is
uninstalled from the GAC.
- The core namespaces have also been modified in keeping with
changes to the core assembly. The Microsoft.Web.*
namespaces have been changed to System.Web.*. In
addition, individual types have been moved to other namespaces.
In your existing applications, you must do the following:
- Ensure that using or import statements
all reference the new namespaces. Any fully qualified
references must also be modified.
- Change references to the server Timer control to
System.Web.UI.
- Change references to the ScriptModule class to
System.Web.Handlers.
- The Microsoft.Web.Extensions.Design namespace has
been renamed to System.Web.Extensions.Design. The types
in the namespace have also moved from
Microsoft.Web.Design to System.Web.Design. In
your application, you must update references and any
using or import statements accordingly.
- Developers who have created extender controls or script
controls that implement the IExtenderControl and
IScriptControl interfaces must add a call to
ScriptManager.RegisterScriptDescriptors in the
Render method of their controls.
- The script compression module has been removed from the
product. Script compression is handled directly in the
script-resource handler. In your existing applications, you
must remove the Web.config entry for the handler.
- The <microsoft.web.extensions> section of the
Web.config file has been renamed to
<system.web.extensions>.
- You must change existing Web.config files, both for the
section itself and the section group.
- The section contains a new sub-section named
<scriptResourceHandler> that is used to
control the caching and compression behavior of the
handler.
- The client global registerNamespace function has
been removed. You should change applications to use the
existing Type.registerNamespace function instead.
- In the Futures release, scripts are referenced by using
simpler names that no longer require the
Microsoft.Web.Resources.ScriptLibrary prefix. You must
modify all references.
The following changes have been made to the client
library:
The following changes have been made for script resources:
- ScriptReference types include a
NotifyScriptLoaded property to instruct the framework to
append the script notification script to resource-based script
libraries.
- The ScriptResource.axd handler has a new section in the
Web.config file that enables developers and administrators to
control caching and compression of script resources served
through the handler.
- The ScriptResource.axd handler supports the substitution
logic in embedded Web resources as supported by the
WebResource.axd handler.
- The ScriptResource.axd handler supports scripts served from
a request to pages directly under the default Web site.
- The ScriptManager control supports UI-culture
fallback logic for file-based static scripts defined using the
ResourceUICultures property of a script reference.
The following changes have been made for extender and script
controls:
- ExtenderControl base class and a new
ScriptControl base class call on the new
ScriptManager.RegisterScriptDescriptors API in their
Render method. Developers using IExtenderControl and
IScriptControl are required to add this call in their
controls’ Render method.
- The ScriptControlDescriptor,
ScriptBehaviorDescriptor and
ScriptComponentDescriptor ID property has been
made consistent with its client representation. The
ScriptControlDescritor and
ScriptBehaviorDescriptor Name property has also
been made consistent with its client-side representation. A
ClientID property has been introduced in
ScriptComponentDescriptor,
ScriptControlDescriptor and
ScriptBehaviorDescriptor.
- An AddScriptProperty API is added to the
ScriptComponentDescriptor allowing developers to set a
property to some JavaScript expression directly.
The following changes have been made for partial page
updates:
- The UpdateProgress control walks the naming
container to locate the AssociatedUpdatePanel
control.
- Script components are automatically registered as
disposable objects with the ScriptManager control.
Client components therefore do not require an HTML element to
be tracked for disposing.
- The ScriptManager.SetFocus method works with HTML
<input type="text" /> elements.
- The MicrosoftWebAjaxWebForms.js library is
referenced in pages only when there is at least one
UpdatePanel control on the page and when the
EnablePartialRendering property is set to
true.
- ScriptControl types are supported in
UpdatePanel controls when the EventValidation
property of the page is disabled.
The following changes have been made for Web service
proxies:
Summary of Changes from RC to RTM
This section summarizes bug fixes and feature additions that
were made between the RC and RTM releases of ASP.NET AJAX version
1.0. Later sections of this document describe the changes in more
detail.
The following are breaking changes.
- The Sys.UI.DomElement.setAccessibilityAttribute and
Sys.UI.Control.set_role accessibility helper APIs have
been removed.
- The Sys.UI.ScriptLoader class is now a private
object and renamed to Sys.UI._ScriptLoader. No APIs are
considered public.
- The script timeout handlers have been removed. This
includes Sys.Application.add_loadTimedout,
Sys.Application.remove_loadTimedout,
Sys.Application.add_scriptLoadFailed,
Sys.Application.remove_scriptLoadFailed,
Sys.Application.get_scriptLoadTimeout, and
Sys.Application.set_scriptLoadTimeout .
- The Sys.Application.queueScriptReference method has
been removed
- The Debug class has been renamed to
Sys.Debug.
- The static Date.parse and Number.parse
functions have been renamed to Date.parseInvariant and
Number.parseInvariant. Similarly,
Date.localeParse and Number.localeParse have been
renamed to Date.parseLocale and
Number.parseLocale.
- The Number.parseInvariant method (formerly
Number.parse) returns NaN if an invalid value is
passed instead of throwing an exception.
- The Date.parseInvariant method (formerly
Date.parse) returns null if an invalid value is
passed instead of throwing an exception.
- The ScriptManager.ScriptLoadTimeout property has
been removed.
- If the <deploymentmode
retail=”false”> setting is on (the default),
the ScriptManager control uses its ScriptMode
property and the ScriptReference settings to determine
whether to serve debug or release scripts. When the
ScriptMode property is set to Auto or
Inherit (the default), the ScriptManager control
determines whether to send debug or release scripts based on
the <compilation debug=”true|false”/>
value in the application’s root-level Web.config file.
The ScriptManager control no longer determines the debug
or release value from the configuration hierarchy. As was true
in previous releases, the ScriptMode setting does not
depend on the debug setting in an @ Page directive.
- The System.Web.UI.Compatibility namespace and the
validator controls that were compatible with asynchronous
postbacks have been removed.
- Accessing static page methods from script is disabled by
default. You must explicitly set the EnablePageMethods
property on the ScriptManager control to true for
the PageMethods client proxy to be generated.
- A System.Web.Script.Services.ScriptHandlerFactory
handler type is now required to enable application services.
You must register this handler in the Web.config file.
- The configuration sections for System.Web.Extensions
(other than the <jsonSerialization> section) are
now marked to prevent their definition below the application
root.
The following changes have been made for registering script
resources:
- Some of the static registration methods of the
ScriptManager class have additional overloads that take
a Page object as a parameter. Scripts can therefore be
registered independently of any UpdatePanel control that
is being updated during the asynchronous postback.
- Script compression is skipped if the browser is Microsoft
Internet Explorer 6.
- The ScriptManager control now supports a
LoadScriptsBeforeUI property that allows page developers
to have script references rendered at the bottom of the form
rather than at the top (which is the default).
- The Name property of the
ScriptControlDescriptor and
ScriptBehaviorDescriptor classes has been added to the
list of properties that are sent to the $create method
if the property is not empty.
- The Function._validateParams function has been added
to the release versions of scripts.
The following changes have been made in the client FX:
- The built-in types will return true when the
isClass method is called on their type.
- Many fixes in the Sys.UI.DomElement.getLocation
method have been made to accommodate variations in
implementations across browser types and versions and to
accommodate the nesting of elements, borders, margins, and
scrollbars.
The fixes for the Futures release are listed in a subsequent
section of this document.
ASP.NET AJAX has been factored into two separate downloads in
preparation for the RTM release. The following lists the original
CTP feature set and indicates where each feature now resides in
the RTM release: the supported ASP.NET AJAX version 1.0 core
release, or the community-supported Futures CTP release.
Feature
|
ASP.NET AJAX 1.0
|
ASP.NET AJAX CTP
|
| Server features |
| Asynchronous client-to-server
networking |
X |
|
| Authentication as a Web service |
X |
|
| AutoCompleteExtender class |
|
X |
| ControlExtender class |
X |
|
| Cross-browser Web Parts
drag-and-drop |
|
X |
| DragOverlayExtender control |
|
X |
| PopupExtender class |
|
X |
| Profile as a Web service |
X |
|
| ScriptManager and ScriptManagerProxy
controls |
X |
|
| Static page methods as Web
services |
X |
|
| Timer control |
X |
|
| UpdatePanel control |
X |
|
| UpdateProgress control |
X |
|
| Client Features |
| Actions components |
|
X |
| Authentication for JavaScript |
X |
|
| AutoCompleteBehavior class |
|
X |
| BatchResponse class |
|
X |
| Behavior class |
X |
|
| Binding component |
|
X |
| Button control |
|
X |
| Calling .asmx Web services from
JavaScript |
X |
|
| Checkbox control |
|
X |
| Click behavior |
|
X |
| Component class |
X |
|
| Control class |
X |
|
| Counter class |
|
X |
| Cross-browser Web Parts |
|
X |
| Data control |
|
X |
| Debug class |
X |
|
| DragDropList control |
|
X |
| DragDropManager component |
|
X |
| DraggableListItem control |
|
X |
| FadeAnimation component |
|
X |
| Floating behavior |
|
X |
| Hover behavior |
|
X |
| Hyperlink control |
|
X |
| Image control |
|
X |
| Input control |
|
X |
| JavaScript Array type extensions |
X |
|
| JavaScript Boolean type
extensions |
X |
|
| JavaScript Error type extensions |
X |
|
| JavaScript Number type extensions |
X |
|
| JavaScript Object type extensions |
X |
|
| JavaScript String type extensions |
X |
|
| JavaScript localization |
X |
|
| JavaScript globalization |
X |
|
| JSON serialization |
X |
|
| Label control |
|
X |
| Layout behavior |
|
X |
| Opacity behavior |
|
X |
| Popup behavior |
|
X |
| Profile for JavaScript |
X |
|
| Selector control |
|
X |
| ServiceMethodRequest class |
|
X |
| Sys.Data and Sys.UI.Data
namespaces |
|
X |
| Textbox control |
|
X |
| Timer control |
Server Timer control added |
X |
| Trace class |
X |
|
| Validator controls |
|
X |
| xml-script support |
|
X |
Detailed Client FX Changes
In the CTP release, "classes" or types were defined using a
closure, effectively the constructor for the class. (Although
these are not classes in the sense understood in the .NET
Framework, we will refer to them as classes here for
convenience.) In the RTM release, the model used is a prototype.
This change was made for several reasons; the following table
contrasts the two models.
| Prototype |
Closure |
| The constructor is required. |
The constructor contains the member
declarations. |
| The notion of "private" is handled by
convention. Members are defined with a name that includes the
“_” prefix. |
Members are truly encapsulated (private) to a
class. |
| Members are effectively shared, which reduces
the memory used by object instances. |
Members are instance-based, which increases
the memory used by object instances. |
|
Prototype provides a good load time in all browsers; in
Mozilla Firefox, prototype has significantly better load
time. In all cases, script load time should be
imperceptible to the end user.
The main performance benefits of prototype are
significantly less memory usage per object, and
significantly faster object instantiation.
|
In Internet Explorer, closure has slightly
better load time. |
| Support for a tool’s IntelliSense and
statement completion can obtain some type information based
simply on reflection without having to create the types. |
Tool support for IntelliSense and statement completion
would require executing code by instantiating classes to
get the required type information.
We are considering this for Visual Studio "Orcas," but
not for Visual Studio 2005.
|
| While debugging, private members can be seen
in the debugger. |
While debugging, private members cannot be
easily seen by the debugger. Viewing member values in a tool
(IDE) would require a number of steps. |
We investigated the performance advantage of prototypes over
closures from many aspects—not just the memory consumed
by object instances, but the instantiation of a typical
application consisting of several classes with a variety of
members. This performance investigation was conducted across
multiple browsers, because the goal is a "best-fit" model across
all browsers.
If you write only ASP.NET pages and use ASP.NET AJAX framework
client objects in custom script or through declarative
xml-script, you should be unaffected by these changes.
The CTP versions had support built-in for closures, to ensure
that the base methods were capable of being called. This support
is removed in the RTM release. You may be able to continue to
have child ‘classes’ that inherit from
prototype-based types, but you should not use closure-based types
in any inheritance chain.
Note In the beta version, there is some notion of
support for closures. This is likely to be removed by RTM. In
essence, however, closures can be used and sub-classed from
prototype-style base classes. Developers should not create
closures in cases where the closure may be used as a base
type.
The following example illustrates the salient points of the
design in the RTM release; further description of the member
patterns is provided later.
registerNamespace("Custom");
// Prototype: Constructor
Custom.Timer = function() {
// Ctor creates private fields and calls base.
Custom.Timer.initializeBase(this);
this._interval = 1000;
this._enabled = false;
this._timer = null;
}
// Prototype: members
Custom.Timer.prototype = {
member1: function() { },
member2: function() { },
...
}
Custom.Timer.registerClass('Custom.Timer', Sys.Component);
In contrast, the CTP release uses a closure model, as shown in
the following example.
Type.registerNamespace("Custom");
// Closure: Constructor and members
Custom.Timer = function() {
Sys.Timer.initializeBase(this, [true]);
var _interval = 1000;
var _enabled;
var _timer = null;
this.member = function() ...
}
Custom.Timer.registerClass('Custom.Timer', Sys.Component);
JavaScript Extensions (Client BCL)
The CTP release contained a number of extensions to the
existing built-in types in JavaScript, and these remain in the
RTM release. However, they were redesigned to avoid potential
conflicts with other AJAX frameworks where possible. (It is in
extensions to the built-in types where collision can occur.)
Beta 2 change: Static Array APIs have
been introduced as described here.
Beta2/RC change: The extensions on the
Array prototype have been replaced by static Array
members that can be passed an Array object.
In the CTP release, there was basic error handling, but this
has been expanded. The Error prototype has been extended
considerably in the RTM release to provide "typed" errors. In
particular, component developers can throw errors (typically in
debug scripts). In the RTM release, you can catch the exception
and can inspect it to obtain further information about the error.
The following example shows basic error handling to provide a
richer exception message.
function checkRange(index) {
if (index > 10 || index < 0) {
throw Error.argumentOutOfRange(“index”, index,
"The index value must be between 0 and 10.");
}
}
function myCallingFunction(value) {
try {
checkRange(value);
} catch (e) {
e.message = e.name + “:” + e.message + “\nIndex value was: “ +
e.actualValue;
throw e; // bubbles up to the default error treatment
}
...
}
When an exception is thrown, the error therefore contains
information that will be handled by the browser.
Class and Type Definition, Reflection APIs
In the CTP release, you could create a number of variations of
types, such as classes, interfaces, enums, and flags. This
functionality has been changed in the RTM release.
Abstract and Sealed Classes
The CTP release allowed you to create abstract classes and
sealed classes. In the RTM release, based on usage and a desire
to improve performance, we removed the concept of a sealed or
abstract class. This enables us to reduce the amount of script in
the library and the complexity and performance impact required to
implement these.
You continue to define namespaces and classes and interfaces
using the Type.register* APIs in the RTM release, but they
have been moved from the Function.prototype property
(where they were in the CTP release) to the Type.prototype
property. This has no impact on you, though, because the CTP
release aliased the window.Type property to
Function. We have therefore changed the recommended usage
of these APIs although either Function.* or Type.*
can be used.
Having all type APIs and reflection-based APIs defined using
the Type.prototype property provides a consistent and
logical design pattern.
Creating Types: Single and Multiple Inheritance
As in the CTP release, the RTM release creates types that can
subclass from base types and can also implement any number of
interfaces. In the CTP release, you could define a type that
subclasses any number of base types. This has changed; in the RTM
release you can use only single inheritance.
The definition of interfaces has been changed between the CTP
release and the RTM release. The new definition reflects the
removal of abstract functions and uses the prototype model. The
following example shows a declaration of the interface in the CTP
release.
Custom.ICustomContract = function() {
this.get_member = Function.abstractMethod;
this.getAnotherMember = Function.abstractMethod;
}
Custom.ICustomContract.registerInterface("Custom.ICustomContract");
Custom.ICustomContract.prototype.get_member = function() { ...;}
Custom.ICustomContract.prototype.getAnotherMember = function() { ... }
The RTM release defines an interface similarly, but now uses
the "typed" exceptions. It does not define abstract methods and
does not define specific implementation. In release mode,
interfaces do not have any code or member definitions.
The following example shows an interface declaration in the
RTM release.
Custom.ICustomContract = function() {
throw Error.notImplemented();
}
Custom.ICustomContract.registerInterface("Custom.ICustomContract");
Custom.ICustomContract.prototype = {
get_member: function() { throw Error.notImplemented();},
getAnotherMember: function() { throw Error.notImplemented(); }
}
When you consume interfaces, you can use reflection-like APIs
to test for the types. When you implement interfaces, you add
their member definitions to the prototype for the type, rather
than to the constructor as in the CTP release.
Beta 2 change: Sys.UI.Key["return"] is now
Sys.UI.Key.enter, and Sys.UI.Key["delete"] is now
Sys.UI.Key.del.
The examples in this section show the differences between the
CTP release and the RTM release for developers creating
Enum and Flag structures. The following example
shows an enum definition in the CTP release.
Type.createEnum("MyEnum", "One", 1, "two", 2);
The RTM release defines enums and flags as similar concepts,
improves the usability of their definition, and allows doc
comments as described later.
MyEnum = function() {
/// <summary>..</summary>
}
MyEnum.prototype = {
One: 1,
Two: 2
}
MyEnum.registerEnum("MyEnum");
A number of enums are available in the client FX, such as
Sys.UI.Key, Sys.UI.VisibilityMode, and
Sys.UI.MouseButton.
Properties, Methods, and Events
In the CTP release, the model for defining properties was
typically to define the getter and setter for the property, using
methods with the prefixes "get_" and "set_". This model remains
in the RTM release, but the member has moved to the prototype
rather being defined in the closure, as described earlier.
Similarly, methods are now defined using the prototype.
There are two general kinds of events: ASP.NET AJAX (client
object) events and events on DOM elements. For DOM element
events, you can use simplified syntax to bind to DOM events in
your classes. For client object events, you typically provide
events that page developers can bind to, and that will be invoked
through your class.
Client FX objects can surface DOM events as their own events
to provide a means for page developers to hook their own
handlers. The following example shows this; the component exposes
the element’s click event as a click event on
the component directly.
In the CTP release, an event on client ASP.NET AJAX objects
was declared as a field in the constructor. Page developers
hooking to the event had their handler called as a result of the
event being invoked from the client object. Client objects hooked
to a DOM element’s event by attaching to the
element’s event during initialization (for example). This
required that the event be disposed in the component's
dispose method, as shown in the following example.
Custom.Button = function(...) {
this.click = this.createEvent();
this.dispose = function() {
if (_clickHandler) {
this.element.detachEvent('onclick', _clickHandler);
_clickHandler = null;
}
Custom.Button.callBaseMethod(this, 'dispose');
}
this.initialize = function() {
Custom.Button.callBaseMethod(this, 'initialize');
_clickHandler = Function.createDelegate(this, this._onClick);
this.element.attachEvent('onclick', _clickHandler);
}
this._onClick = function() {
this.click.invoke(this, Sys.EventArgs.Empty);
...
}
The preceding example also shows the model of calling
attachEvent to attach the element’s click
event. This is closer to the model for Internet Explorer, as
demonstrated by the example for onclick.
Script to provide your own handlers for object events might
look like the following.
// Simple global handler.
var b = new Custom.Button();
b.click.add(OnClickHandler);
function OnClickHandler() {
...
}
This design has been modified for various reasons. These
include improving performance; providing a programming experience
familiar from the .NET Framework; and following ECMAScript
standards designs, as suggested in customer feedback. In the RTM
release, you simply provide events that follow a naming pattern,
in the way properties are exposed, using the "add_" and "remove_"
naming convention. Tools can potentially interpret this
pattern — for example, tools could use this pattern to
determine events in IntelliSense.
In high-level components, you now simply add a handler to an
internal EventHandlerList object that is exposed through
the get_events( ) member on the Component base
class. Unlike the CTP release, the RTM release creates the event
and event hookup at the time it is required, rather than every
time the object is created. The following example demonstrates
the RTM release model.
In Beta 2, a simplified syntax has been provided that
automatically creates the delegate and that can be used to
associate a number of DOM events and handlers at the same time.
The following example shows how this is done.
Custom.Button.prototype = {
initialize: function() {
Custom.Button.callBaseMethod(this, 'initialize');
// Create the handler and add the DOM handler
this._handler =
Function.createDelegate(this, this._onClickHandler);
$addHandler(this.get_element(), 'click', this._handler);
..
// Alternative syntax for single or multiple handlers.
// When multiple handlers are involved, this
// syntax greatly reduces the amount of code you need
$addHandlers(this.get_element(),
{ click: this._onClickHandler,
mouseover: this._onMouseOverHandler,
mouseout: this._onMouseOutHandler,
keydown: this._onKeyDownHandler,
focus: this._onFocusHandler,
blur: this._onBlurHandler
}, this);
}
add_click: function(handler) {
// Expose an event in this class
this.get_events().addHandler('click', handler);
},
remove_click: function(handler) {
this.get_events().removeHandler('click', handler);
},
dispose: function() {
// Potential for dispose to be called more than once
if (this._handler) {
$removeHandler(this.get_element(), 'click',
this._handler);
delete this._handler;
}
..
// Alternative syntax that can remove multiple handlers
// attached through $addHandlers
$clearHandlers(this.get_element());
Custom.Button.callBaseMethod(this, 'dispose');
},
_onClickHandler: function() {
// Invoke any page developer handlers that may be attached
var ev = this.get_events().getHandler(this._handler);
if (ev) {
ev (this, Sys.EventArgs.Empty);
}
}
}
The design demonstrates the pattern of creating event handlers
at the required time. It uses the static methods of a new type
named DomEvent to add and remove event hookups for the DOM
element events themselves, using a standards-based model. Under
the hood, these abstracted APIs provide browser compatibility
support. Notice that in this example the aliases
$addHandler, $removeHandler, $addHandlers,
and $clearHandlers are shown. These are described
later.
In cases where you might be creating a number of DOM event
hookups in client components and then removing them in the
dispose method, you can use APIs or aliases that encompass
more than one event hookup and that create the delegate for
you.
If you are wiring up your own handler, you now write code like
the following. The event parameter is optional, but
allows you to inspect the event, such as determining which button
caused the click.
var b = new Custom.Button();
b.add_click(OnClickHandler);
function OnClickHandler(event) {
..
}
The CTP release used an abstraction model for browser
compatibility that focused on APIs based on Internet Explorer. It
used the server to provide a compatibility layer when the browser
was not Internet Explorer, implemented by downloading an
additional JavaScript file.
In the RTM release version, this abstraction is retained, but
it is based on standards and other improvements to the design. As
a consequence, server intervention is no longer required.
Instead, the client contains simple browser detection code based
on capability, and abstraction APIs and other component-based
APIs use such abstractions. For example, the event model
described earlier uses the DomEvent.addHandler and
DomEvent.removeHandler methods in a more standards-based
way. Note the naming pattern of the event when using click
instead of onclick. These API names are also consistent
with the naming patterns used in components and types in the
client.
Building Debug and Release Scripts
Our design scenarios call for us to provide a robust tools
experience for ASP.NET AJAX. This requires supporting debug
scripts and the ability to create release scripts for production
environments.
In the CTP release, there was little difference between the
debug and release versions of scripts, other than the release
versions were compressed to remove unneeded white space. In the
RTM release there has been a considerable effort placed on
providing a tools and programming experience that revolves around
the use of debug versions of scripts. Debug versions of scripts
now contain:
- Support for doc comments. These are included to potentially
augment IntelliSense in a tool, and to provide information to
any developer using the APIs.
- Error handling through the use of the Error
extensions described earlier.
- Named functions. Rather than anonymous functions, functions
are pseudo-named, so that you get additional information, such
as obtaining context within a stack trace.
If you develop components, you can now provide
type-description information in the debug scripts that define
your custom types. This information will be useful for
potentially augmenting the type information defined within Visual
Studio “Orcas” for IntelliSense and for statement
completion. (It will not be supported in Visual Studio 2005.) In
addition, doc comments make it possible to use the Client FX
validation model for compiler-type checking.
Doc comments offer the following features:
- You can define comments immediately in the constructor and
in members.
- You can define comments in the property getter, which
infers the setter, and also in the event adder.
- You can define comments in the interface constructor.
- Comments support complex parameter or return types.
An example of RTM release doc comments is shown in the
following snippet of a border behavior.
Type.registerNamespace('Custom.UI');
Custom.UI.BorderBehavior = function(element) {
/// <summary>A border behavior</summary>
/// <param name="element">Associated element</param>
Custom.UI.BorderBehavior.initializeBase(this, [element]);
}
Custom.UI.BorderBehavior.prototype = {
...
get_color: function() {
/// <summary>Color</summary>
/// <value type="String"/>
return this._color;
},
..
}
Defining Type Descriptors
In the CTP release, you created objects that implement
ICustomTypeDescriptorProvider as a result of inheritance
from the Component base class. You created a
getDescriptor method and returned a TypeDescriptor
object that was used to support xml-script declarative blocks and
bindings.
The following example shows the definition for Button
control in the CTP release. (Note the use of the closure
model.)
Custom.Button = function(associatedElement) {
Custom.Button.initializeBase(this, [associatedElement]);
..
this.getDescriptor = function() {
var td = Sys.UI.Button.callBaseMethod(this, 'getDescriptor');
td.addProperty('command', String);
td.addProperty('argument', String);
td.addEvent('click', true);
return td;
}
In the RTM release, type descriptors have been removed for
several reasons:
- Xml-script requires considerable additional script and load
processing logic, which affects script size and performance.
This added unnecessary overhead in the more common cases where
server controls produce rich client behavior.
- Xml-script is oriented to the client, declarative
programming model, which is currently included only in the
Futures release.
- Any behavior defined with declarative xml-script can be
created by writing JavaScript code, without requiring the
overhead of xml-script processing. (Of course, declarative
xml-script might be easier with proper tools support.)
- There is currently no tool support for the declarative
xml-script, making it tedious and verbose to author.
The features included in the Futures release continue to work
with the RTM release, including xml-script. Therefore, you can
write a component that can also be used by page developers who
work with xml-script. To support this capability, the Futures
release includes a TypeDescriptor object and is capable of
generating such an object through a simple JSON field that is
defined by the component itself. This is done without defining
any true types in the RTM release.
The following example shows the same Button example
from earlier, but here as done in the RTM release.
Custom.UI.Button = function(associatedElement) {
Sys.UI.Button.initializeBase(this, [associatedElement]);
}
Custom.UI.Button.prototype = {
..
}
Custom.UI.Button.descriptor = {
properties: [ {name: 'color', type: String } ],
methods: [ .. ],
events: [ {name:'click'}, .. ]
}
You can add the readOnly attribute, ensuring that the
property has a default value, as shown in the following
example.
MyControl.descriptor =
{ properties: [{name: "title", type: String, readOnly: true}] }
If you need to refer to a DOM element, use
isDomElement:true, as in the following example.
MyControl.descriptor =
{ properties: [{name: "...", isDomElement:true }] }
Similarly, if the component defines some property that is a
reference to another component (perhaps in a composition form),
then the TypeDescriptor should reference the type. The
following is an example.
MyControl.descriptor =
{ properties: [{name: "...", type: Custom.Button }] }
If you use xml-script in the Futures script, you can create a
tag based on the type’s name. The Futures script will
perform all the necessary steps to use the type descriptor.
Higher-level Component Framework
The higher-level component feature set has been modified based
on customer feedback, and for performance and working-set
considerations. As shown in the earlier Button example,
the DomEvent class uses a standards-based approach to
provide a consistent abstraction API for DOM event hookup. This
abstraction works across multiple browsers.
Some APIs have been moved from their CTP release locations
(often the Control class) to a new DomElement type
in the RTM release, where they are defined as static functions.
This reduces the size of the Control class and moreover
allows you to use these helper methods, which typically wrap DOM
element functionality, without instantiating a Control
object. The following example shows how to use the
DomElement object.
Sys.UI.DomElement.getLocation($get('AddressLine1'));
Note the use of a new $get alias in this example, which
is explained later.
Component, Control, and Behavior Classes
The CTP release contained the Component, Control
and Behavior classes, which defined many APIs and provided
significant functionality. Both Control and
Behavior are of type Component.
This model continues in the RTM release. However, the
semantics of these classes have been modified based on our study
of their usage and on their original design implications. For
example, in the CTP release, a Control instance was
associated with a particular DOM element (see the constructor),
and you could access that control through the DOM element.
However, behaviors, although indirectly associated with a DOM
element, required a Control instance and were maintained
by Control using a collection property.
The RTM release version makes working with DOM elements much
more flexible. Both Control and Behavior are
similar in concept and both are associated with a particular DOM
element. However, they are now independent of each other.
In the RTM release, you can associate a single Control
instance with a DOM element, and access it through the
control expando, as in the CTP release. If a behavior has
a Name property, you can also reference the behavior by an
expando based on its name. Multiple behaviors can be associated
with the DOM element. The following example demonstrates
$create, and uses a new $get alias defined in the
RTM release to reference the controls and behaviors types.
// Add a control and behavior to the GoShopping DOM element.
$create(Custom.UI.Button, {}, {'click':'myHandler'}, {}
$get('GoShopping'));
$create(Custom.UI.BorderBehavior, {'name':'border'}, {}, {},
$get('GoShopping'));
// Page developer accesses Button using the DOM element directly.
var gs = $get('GoShopping');
gs.control.set_text('Sale items');
gs.border.set_color('red');
// Page developer obtains the behavior using the $ separator.
var bb = $find(‘GoShopping$border);
Creating and Finding Components and Elements
In the CTP release, you were able to instantiate components in
JavaScript, set properties, and call initialize.
Alternatively, you could reference them using xml-script. The
models for working with components in the RTM release:
- Create components in JavaScript as before.
- Use a new alias named $create for components that
instantiates the component and sets properties, calls
initialize, and so on. This is a powerful model that is
also leveraged by server controls.
- Use xml-script, which is still supported in the Futures
release, and which performs the same logic as the
$create alias in the RTM release.
In the RTM release, when a component is instantiated with
$create, a reference to the component is added to the
global Application object. An alias is then available that
allows page developers to locate components in cases where the
page developer did not create the component—for
example, the page developer can find a component that was created
as a result of xml-script.
$object, $find, and $create Aliases
In the CTP release, you could use the
$object('GoShopping') construct to reference a component
created as a result of xml-script. The Futures release will
continue to support this alias.
In the RTM release code, we have introduced the $find
method. You can use this method to locate all components created
either by xml-script or by the $create alias in
JavaScript. This means that you can get references to objects
created by server controls and extenders, as well as by your own
JavaScript and by xml-script declarations.
Note In the beta version the $find syntax can
be used to locate components, behaviors, and controls registered
with the application using their ID. Controls obtain their ID
from their DOM element’s ID. Behaviors obtain can obtain a
unique ID which defaults to
elementId$className — for example,
AddressLine1$AutoCompleteBehavior — and
are registered with Application.
$create provides a powerful, concise syntax for
creating a component in the client. When combined with
Application methods, it even supports the scenario where
circular references can be made between components in the client,
as described in the "Application Object Life Cycle" section later
in this document.
$ and $get
The CTP release defined a global alias named $( ) that
mapped to the document.getElementById function. The
$( ) alias is not supported in the RTM or Futures
releases. Because we have a goal to not conflict with other AJAX
frameworks, $( ) cannot be used; other frameworks define
this function also. In its place, the RTM release defines a
$get( ) function that performs the same task.
$addHandler, $removeHandler
The $addHandler and $removeHandler aliases in
the RTM release provide a shorthand notation to create DOM event
hookups and removal. Some examples were shown in the RTM
Button control example earlier. In particular, however,
the handler is passed a Sys.UI.DomEvent instance that
provides a browser compatible event object. In the CTP model, you
wrote handlers that would rely on the window.event global
reference instead, which was not browser independent.
$addHandlers, $clearHandlers
Beta 2 change: $addHandlers and
$clearhandlers methods have been introduced.
In many cases you want to hook up several handlers (delegates)
to DOM events for the component. Rather than manually creating
all the delegates and defining the handler for each, and then
removing the handlers in the dispose event, you can use a
condensed syntax to add and remove multiple handlers. The
following provides an example.
...
initialize: function() {
...
var el = this.get_element();
$addHandlers(el,
{[ 'mouseover': this._mouseHoverHandler,
'mouseout': this._mouseOutHandler,
'focus', this._focusHandler,
'blur', this_blurHandler
]}, this);
Custom.UI.Hover.callBaseMethod(this, 'initialize');
},
dispose: function() {
if (!disposed)
$clearHandlers();
Custom.UI.Hover.callBaseMethod(this, 'dispose');
},
...
Application Object and Life Cycle
Beta 2 change: Several new events have been
introduced that handle errors when loading script libraries. The
Sys.Application.initialize method might be called prior to
window.onload (but after the DOM is ready). Page
developers need to ensure that their page logic is performed in
the pageLoad function.
Beta 2 change: Script loading is performed
through a client object that ensures scripts begin to be loaded
(sequentially) and components begin to be created before the
window.onload event. The components' initialize
method is called as a result of the init event raised by
Sys.Application.
RC change: The default model for script loading
has been modified. Library scripts are rendered declaratively at
the top of the form, rather than being dynamically injected at
the end of the form by calling
Sys.Application.queueScriptReference. This means that the
library scripts are available prior to the UI loading. The
intention in the RTM release is to provide a flag on the
ScriptManager control that enables page developers to
select the script library loading process (before or after the
UI) and manage their application scenario effectively.
Instance scripts (those generating the client components
through the $create method) continue to be queued with the
ScriptLoader method at the end of the form. Page
developers should continue to use the client pageLoad
function for your client page logic. Component developers may
want to attach to the load event of the
Sys.Application object.
RTM change: A property named called
LoadScriptsBeforeUI has been added to the
ScriptManager control with a default value of
false. The flag enables developers to have the
ScriptManager control render the script references either
before the UI markup of the page or after it. Loading script
after the UI might require changes to your application so that
unexpected behavior does not occur before your application
scripts are loaded and components are initialized. When scripts
load after the UI, the page begins to appear quickly but the
application may not yet be initialized. The page might not be in
its final state, or users might interact with elements before
script has finished downloading and executing.
RTM breaking change: The Sys.ScriptLoader
type has been made private and all members of this type are
therefore also private. This change has been made given the
change to the model for rendering script references, as described
above.
RTM breaking change: Because scripts are loaded
through <script> tags, there is no requirement for
the Sys.Application script-loading event handlers, so they
have been removed. This includes the following events:
- Sys.Application.add_loadTimedout
- Sys.Application.remove_loadTimedout
- Sys.Application.add_scriptLoadFailed
- Sys.Application.remove_scriptLoadFailed
- Sys.Application.get_scriptLoadTimeout
- Sys.Application.set_scriptLoadTimeout
The ScriptManager.ScriptLoadTimeout property of the
ScriptManager class has been removed.
Beta 2 change: "Dynamic" script library loading
supports the Safari browser. File-based script libraries are
required to have the following code at the end of their script
file to notify the Sys.Application object that they have
been loaded:
if(typeof(Sys) !== “undefined”)
Sys.Application.notifyScriptLoaded();
RC change: Script library references that result
from an embedded Web resource (typically those from extender
controls or script controls) by default have the preceding script
automatically injected at the end of the script library. However,
component developers can control whether this script is appended
by setting the NotifyScriptLoaded property on a
ScriptReference collection.
Similarly, if a page developer references a script resource in
an assembly using the ScriptManager control, the
NotifyScriptLoaded property can be declaratively defined
on the ScriptReference element.
RTM change: Adding a call to the
Sys.Application.notifyScriptLoaded method in script files
is necessary only for asynchronous postbacks, but it is
recommended that developers add a call to this method to script
files that are served from disk.
The CTP release had the concept of both a Runtime and
an Application object. In the CTP release, the
Application object was responsible for hooking to window
events, and for locating the page developer’s
pageLoad function (the load event handler) and
pageUnload function (the unload event handler). The
pageLoad function was guaranteed to be called after all
the scripts had been loaded and after any objects defined in
xml-script had been created and initialized.
The RTM release brings Runtime and Application
objects together into a single Application object. The RTM
release continues to define the load and unload
events, but also introduces an init event, which is
typically used to create objects (using the $create
alias). You can use the load event (mapped to
pageLoad) to manipulate objects as before. In the RTM
release, the load event is also raised during partial-page
refreshes, and you can therefore run code in the pageLoad
function to manipulate objects that may have been recreated as a
result of the round trip.
Objects that are created using the $create syntax are
guaranteed to be instantiated; it also guarantees the
beginUpdate method is called, properties are set, and the
component's endUpdate and initialize method are
called. In addition, objects can be registered with
Application, thus allowing components to be managed and
found through $find.
The $create method defines the type to create, simple
properties, event hookups, reference properties, and the optional
DOM element. $create can handle scenarios in which
components have references to other components. Ordinarily page
developers do not need to need to call $create, because
the server FX handles all $create logic from extender
controls and script controls.
Property Change Notification
Both the CTP and the RTM releases define property-change
events. In the RTM release, if you are developing components, you
continue to raise the property-changed event for properties in
your components that may require binding, or for external event
listeners.
The base component type is INotifyPropertyChange.
In the CTP, the base Sys.Component type implemented the
Sys.IDisposable interface, which defines the
dispose method. This continues in the RTM release.
However, a further interface has been introduced, named
Sys.INotifyDisposing, which is defined in
Sys.Component. This interface allows bindings in the
Futures to listen to objects being disposed, and therefore be
separate components in their own right.
Objects are required to be disposable to support the
UpdatePanel scenarios, so you should be sure that you
implement the dispose method in such a way that it handles
being called more than once. In the Button example shown
in the events section, the dispose method shows checking
for the click handler and calling $removeHandler and
delete only if defined. Calling the $clearHandlers
function performs this logic automatically for handlers that were
bound using the $addHandlers function.
You should also ensure that any child components or objects
being manually disposed are checked, because Application
does not guarantee the order of objects being disposed
automatically.
The CTP release defined bindings on a component. Therefore a
binding required a component so that the binding could be added
to the component.
The RTM release does not directly support bindings, but given
the Sys.INotifyDisposing interface, bindings in the
Futures scripts can (for example) be notified of objects being
disposed and therefore be self-managing. Bindings in the Futures
scripts can therefore be created without a component or demand on
the RTM release; this also means that bindings can be declared
more freely than in the CTP release.
Bindings in the Futures release now obtain both a source and a
target object reference and can listen to the disposing event of
those objects. When an object is being disposed, the associated
binding can now dispose of itself independently.
RTM breaking change: The client Debug
class has been renamed to Sys.Debug. This avoids any
potential collision with other frameworks.
The Sys.Debug class allows you to output debug
information to the browser console, to the Visual Studio debugger
output window, and in Internet Explorer, to a
<textarea> element in the page. Sys.Debug
supports methods to generate trace information, to throw an
assert, and to display an object dump. The following snippet
shows a simple example of using a <textarea> element to
display debugger information.
This is the code in the script file:
onClick: function(e) {
this.set_checked(!this._checked);
Sys.Debug.trace("Element: " + this.get_element());
Sys.Debug.traceDump("Component: " + this);
This is the code in the .aspx file:
<script type="text/javascript">
function pageLoad() {
$create(Custom.UI.CheckBox,{},{},{}, $get("checkbox"));
}
</script>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager runat="server" ID="SM01">
<Scripts>
<asp:ScriptReference Path="CheckBox.js" />
</Scripts>
</asp:ScriptManager>
<span id="checkbox" tabindex="0">Click me</span>
<br /><br />
<textarea id="traceConsole"
style="font-family:tahoma;font-size:small;"
cols="100" rows="20" ></textarea>
</div>
</form>
</body>
The output will look like this:

Globalization and Localization
Beta 2 change: Globalization and localization
features have been added.
RC change: In the RC release, Date and
Number parsing can also be performed using the
globalization feature set using the new parse and
localeParse methods.
RTM breaking change: The Date.parse and
Number.parse functions have been renamed to
Date.parseInvariant and Number.parseInvariant.
Similarly, the Date.localeParse and
Number.localeParse functions have been renamed to
Date.parseLocale and Number.parseLocale. These
changes make the APIs consistent. More importantly, they
eliminate potential problems for applications that rely on the
specific behavior of the built-in parse functions of these
types.
Globalization in the client FX is supported through the
Sys.CultureInfo type. This type defines two JSON objects,
InvariantCulture and CurrentCulture.
In the CTP release, the CurrentCulture type was set
through a server handler that was called from the client
application. In the RTM release, this type is written in-line to
the page. The change removes a callback to the server, but an
inline type cannot be cached in the client. However, the objects
are small.
The server framework is capable of creating the client
Sys.CultureInfo.CurrentCulture by serializing the
.NET CultureInfo object for the given thread’s
CurrentCulture at the point of rendering in the
ScriptManager control. This means that you can
programmatically define the Culture using server
techniques in ASP.NET 2.0, which by default use a mapping from
the ACCEPT_LANG header of the incoming request. Typically you
will set Culture=”Auto” and
UICulture=”Auto” in the @ Page
directive of the page, or set these values directly, such as by
calling the InitializeCulture method in the generated page
class.
In the client, your code, and any type that results from
server extenders, can use the format and
localeFormat APIs added to the Number, Date,
and String types, and the parseInvariant and
parseLocale APIs added to the Date and
Number types. The following sample demonstrates formatting
a Date object with a predefined CultureInfo object
and parsing input for a Date object.
var d = new Date();
$('DateLocale').innerHTML = d.toFormattedString("M");
// Rendered output assuming a CultureInfo obtained for Culture=”fr”
// 31, octobre
In the RTM release, the new APIs allow specific
formatting.
var d = new Date();
$get('DateLocale').innerHTML = d.localeFormat("M");
// Rendered output assuming a CultureInfo obtained for Culture=“fr”
// 31, octobre
// Parse. This assumes that the input value follows the 'd' format'
var s = $get('TextBoxDate').value.trim();
var d = Date.parseLocale (s, "d");
$get('Date').innerHTML = d;
To use globalization support, you must explicitly set the
ScriptManager.EnableScriptGlobalization property to
true, as shown in the following example. As mentioned, you
will find a JSON object written inline to the page.
<asp:scriptmanager runat=”server” EnableScriptGlobalization=”true” />
RC change: A number of bug fixes have been made
in the RC release. In particular, the ResourceUICultures
support on path-based script references has been fixed.
Localization support has been added to the RTM release. The
mainline scenarios that are supported are:
- Client components have UI elements, exception messages, and
other items that are private to the component. In this case,
the client component can be provided localized resources
through two means: using an embedded resource (and therefore a
satellite assembly), or as part of the library script reference
itself.
- Client components have public properties that can be set
and therefore localized by the page developer directly. There
are two possible scenarios here also: the component is handled
through a server extender control or script control, or the
component is created directly in the client by the page
developer.
Localized resources for a component are provided as a JSON
object and referred to in the component through the object. For
example, in the client FX, exception messages are thrown in debug
scripts where the message is referred to using the type
Sys.Res.<ExceptionMessageKey>.
These objects are typically appended to the script reference
automatically by the script resource handler when it reads
scripts from embedded resources in server assemblies
Localized Resources from Server Assemblies
RC change: The ScriptResource.axd handler can be
configured for caching and compression. The handler now also
supports the resource substitution logic that is supported by the
WebResource.axd handler. You can add substitution references in
the embedded Web resources that are then handled by the
ScriptResource.axd handler.
Note : The substitution code
(<%=WebResource() %>) inserts a
Webresource.axd URL, and the
<%= ScriptResource() %> code inserts a
ScriptResource.axd URL.
RC change: The custom client type and namespace
that is generated from the embedded server resource are
registered automatically.
A script library’s resources are served and generated by
the server based on the incoming browser's ACCEPT_LANG header.
The script resource handler added in the RTM release is
responsible for generating a stream to the client that contains
both the script library code and the automatically generated
resource for the given UICulture value. If needed, you can
use ASP.NET code to set of the UICulture value; using the
ACCEPT_LANG is simply the default model.
Component developers can leverage the .NET localization model
for satellite resources (packaging, servicing benefits), and rely
on automatic generation to serve the relevant resource through
any UICulture fallback model. This means the normal .NET
localization workflow and toolset all contribute to this
model.
By default, localization is not enabled in a Web page; to use
localization, you must set the
ScriptManager.EnableScriptLocalization property to
true, as shown in the following example:
<asp:scriptmanager runat=”server” EnableScriptLocalization=”true” />
The following snippet demonstrates creating a custom extender
control that has localized resources. These resources are
referenced through a custom type in the client. Assume that the
project is a class library named Custom.UI.ToggleButton.
// AssemblyInfo.cs
// Define the script resources attributes.
// The WebResource defines the script library for the client behavior
[assembly:webResource("Custom.UI.ToggleButton.ToggleButtonBehavior.js"
, "text/javascript")]
// The ScriptResource attribute references the WebResource attribute and
// points to the name of the embedded RESX(as a resource), and defines the
// custom client type.
[assembly: ScriptResource("Custom.UI.ToggleButton.ToggleButtonBehavior.js",
"Custom.UI.ToggleButton.ToggleButtonBehavior", "Custom.UI.Res")]
// ToggleButtonBehavior.js
// Marked as embedded resource in the class library.
..
this.get_element().innerHTML = Custom.UI.Res.unhoverText;
..
// ToggleButtonBehavior.resx, ToggleButtonBehavior.fr.resx
// ToggleButtonBehavior.ja.resx, ..
// Marked as embedded resource. These are compiled by Visual Studio to
// embedded .resource ‘files’ .
// The neutral culture is embedded in the main assembly, and others are
// embedded in satellite assemblies under the culture folder structure
In the consuming page for this extender, you declare the
extender and the ScriptManager control as shown earlier.
When the page runs, the ScriptManager control generates a
script reference to the library script using the
ScriptResource.axd handler. The request instructs the handler to
obtain the library script and also to obtain the relevant
resource for the given UI-culture. This resource set is then
serialized to the defined custom type as indicated in the
ScriptResource attribute above.
The following snippet demonstrates the script library output
that is sent to the client.
..
// Type generated by the framework automatically
Type.registerNamespace('Custom.UI');
Custom.UI.Res={
""unhoverText":"©±",
""hoverText":"¤µ©±"
};
Localized Resources from Static, File-based Scripts
A script library’s resources are rendered by the server
using a model that involves the ScriptManager control, but
there is no built-in, on-the-fly process for combining the
library with the relevant resource for the current
UICulture. Instead, the server interprets the
UICulture as described above, but the script library and
its resource are expected to already have been combined prior,
potentially through a build process. The build process could
involve the assembly-based library and its resources and
satellite assemblies.
In order to select the correct script file to serve for the
request, you instruct the ScriptManager control which
ResourceUICultures values are supported by using an
attribute on the script reference, as shown in the following
example:
<asp:scriptmanager runat="server" EnableScriptLocalization="true"
ScriptMode="Release">
<scripts>
<asp:scriptreference path="~/scripts/Custom.UI.js"
ResourceUICultures="en-GB, fr-FR, fr-CA, ja-JP, de-DE" />
</scripts>
</asp:scriptmanager>
// If the UICulture on the thread is ja-JP, the following
// script reference is rendered.
// (Note that ScriptMode is set to "Release".)
<script src=”../scripts/Custom.UI.ja-JP.js />
The ScriptManager control infers the UICulture
from the thread in the server, interprets the script reference
(providing some means of fallback), and sends a script library
that corresponds to a given UICulture.
Calling Web Service Methods from Script
The client proxy design for Web services has been modified to
simplify method invocation, and to provide greater flexibility in
associating method calls to callback functions.
In the CTP release method definition, client invocation and
callback was defined as shown in the following examples. The
first example shows the CTP release server code that defines a
Web service method.
public class MyService: System.Web.Services.WebService
{
[WebMethod]
public string MyWebMethod(int param1, string param2) {
...
}
The next example shows the CTP release client code that calls
the method.
// Invoke method, specifying a "succeeded" callback function.
MyNS.MyService.MyMethod(126, "my value", OnComplete,
OnTimeout, OnError, onAborted, "MyUserContext");
// Callback function.
function OnComplete(result, response, userContext) {
// Use result.
}
The next two examples show the corresponding RTM release
method definition. The RTM release server method looks like the
following example.
[ScriptService]
public class MyService: System.Web.Services.WebService
{
[WebMethod]
public string MyMethod(int param1, string param2) {
...
}
The RTM release client code to call the method looks like the
following example.
// Invoke method, specifying callback functions and user context.
MyNS.MyService.MyMethod(126, "my value", OnSuccess, OnFailure,
"MyUserContext");
// Callback function
function OnSuccess(result, userContext, methodName) {
// Use result.
}
In the RTM release, you can specify default callback functions
and a user context, so that calling the Web service method does
not require you to pass these as parameters. The following client
script sets default callback functions and then calls the Web
service method twice with different parameters.
var Fs = MyNS.MyService;
Fs.set_defaultSucceededCallback(OnSuccess);
Fs.set_defaultFailedCallback(OnFailure);
Fs.set_defaultUserContext("MyUserContext");
Fs.set_timeout(100);
// Invoke method without specifying callback functions or user context.
Fs.MyMethod(126, "value one");
Fs.MyMethod(456, "value two");
Server Attributes
In the CTP release, server attributes already defined in the
.NET Framework were used for specifying behavior when Web service
methods were called. In the RTM release, new server attributes
are defined to specify particular behavior. This change was
driven by security concerns and to avoid reusing existing
attributes where the semantics are different.
Specific changes to Web method attributes are:
- A [ScriptService] attribute is required on the Web
service class in order for its methods to be called from client
script.
- The [ScriptIgnore] attribute excludes properties or
fields from JSON serialization, so that they do not appear on
script proxies for a server type. This corresponds to the
[XmlIgnore] attribute in the CTP release.
- The [GenerateScriptType( )] attribute generates
script proxies for server types, in addition to types used as
input parameters or return types on Web methods. This attribute
can be added to the Web service class or to any Web service
method. It corresponds to the [XmlInclude( )] attribute
in the CTP release.
WebServiceProxy Class
The WebServiceProxy class was added to allow invocation
of Web services that are not declared as service references with
the ScriptManager control (using the
<asp:ServiceReferences> element).
WebServiceProxy is also used as an abstract JavaScript
base class for generated JavaScript proxies for any Web services
that are declared in the ServiceReferences collection.
Support for WCF Web Services
You can no longer call Windows Communication Foundation (WCF)
Web services (.svc files) from script in the RTM release. This
capability is superseded by an improved implementation which we
plan to make available with full WCF integration in upcoming
"Orcas" CTP releases.
Advanced Networking Scenarios Not Available in the RTM
Release
The following networking features of the CTP release will not
be available in the RTM release:
- The iframe executor. This feature provided support
for cross-domain calls, and is not available in RTM release in
part because of security concerns.
- The following infrequently used features:
- Assembly-based method calls.
- InitialData control.
- Batching of Web service calls.
RTM breaking change: The RTM release requires
additional <httpHandler> mappings in the Web.config
file, which is used by the client application service
proxies.
In the RTM release, we provide a simplified and more flexible
design for using the Authentication and Profile services from
script. The design is aligned with the design for calling
user-defined .asmx Web services from script (see
“Calling Web Service Methods from Script”
earlier).
The application services in the RTM release requires entries
in the Web.config file. For more information, see the section on
configuration.
The RTM release version of the Profile service, in keeping
with the Web service script proxy model, is not implemented as a
component. However, an implementation of the Profile service as a
component is provided in the Futures release.
The primary changes in the Profile service between the CTP and
the RTM releases are:
- The class name has changed from Sys._Profile to
Sys.Services._ProfileService.
- The global instance has moved from Sys.Profile to
Sys.Services.ProfileService.
- You can specify default callback functions for save, load,
and errors.
- New save and load methods have been added
that take a string array of parameters.
- Profile groups are now supported.
- You can preload profile properties using
ScriptManager and ProfileServiceManager control
markup.
- The AutoSave feature has been removed.
- The saved, loaded, and propertyChanged
events have been removed.
The version of the Profile service provided in the Futures
release fills the gap between the CTP release Profile component
and the RTM release Profile proxy, and has the following
features:
- The class name is
Sys.Preview.Services.Components.Profile.
- The xml-script markup is the same
(<profile ...>).
- The component automatically loads the profile on page load
if no alternative preloading is specified.
- The component includes the AutoSave feature.
- The component includes saved and loaded
events.
- The component includes getProperty( ) and
setProperty( ) methods.
- The component can be the target or source for a
Binding component.
The following samples illustrate the use of the Profile
service in the Futures release.
The first example illustrates preloading profile
properties.
<!-- Preload specific properties with the page -->
<asp:ScriptManager>
<ProfileService
Path = "~/myapp/profileserviceurl.asmx"
LoadProperties = "SimpleProperty, Group.GroupedProperty" />
</ asp:ScriptManager>
The following example illustrates loading profile
properties.
// Load specific properties, after setting default completed
// and failed callback functions. Sys.Services.ProfileService.load(["SimpleProperty",
"Group.GroupedProperty"]);
// Load all properties marked as "read access" in the Web service,
// after setting default completed and failed callback functions.
Sys.Services.ProfileService.load();
// Specify explicit callbacks rather than using defaults. "88" is
// passed to the callback function as user context.
Sys.Services.ProfileService.load(props, loadCompletedCallback,
failedCallback, 88);
The following example illustrates accessing properties.
var x = Sys.Services.ProfileService.properties.SimpleProperty;
var x = Sys.Services.ProfileService.properties.Group.GroupedProperty1;
var x = Sys.Services.ProfileService.properties.Group.GroupedComplexTypeProperty.AddressLine1;
The following example illustrates changing property
values.
Sys.Services.ProfileService.properties.SimpleProperty = "value";
if(!Sys.Services.ProfileService.properties.Group) {
Sys.Services.ProfileService.properties.Group =
new Sys.Services.ProfileGroup();
}
Sys.Services.ProfileService.properties.Group.GroupedProperty1 =
"group value";
Sys.Services.ProfileService.properties.Group.GroupedComplexTypeProperty =
{ AddressLine1: "abc", AddressLine2: "xyz" };
The following example illustrates saving property values.
// Save specific properties, after setting default success and
// fail callback functions.
Sys.Services.ProfileService.save(["SimpleProperty",
"Group.GroupedProperty"]);
// Save all properties in the .properties object, after
// setting default completed and failed callback functions.
Sys.Services.ProfileService.save();
// Specify explicit callbacks, rather than using defaults. "88" is
// passed to the callback function as user context.
Sys.Services.ProfileService.save(props, saveCompletedCallback,
failedCallback, 88);
The following example illustrates the completed callback
function signatures.
function loadCompletedCallback(numPropertiesLoaded, userContext, methodName) {...}
function saveCompletedCallback(numPropertiesSaved, userContext, methodName) {...}
The following examples illustrate the failed callback function
signature.
function failedCallback(errorObject, userContext, methodName) {...}
The changes for the Authentication service between the CTP and
the RTM releases are:
- You can set default callback functions for login, logout,
and errors.
- The login and logout functions can take a
redirectUrl parameter that specifies a URL to redirect
to on completion.
- The login function takes a customInfo
parameter that is reserved for future use, and should be set to
null.
- The get_isLoggedIn method has been added. This
method does not contact the server; instead, it is up-to-date
with respect to the current component. If you call the
login function with no redirectUrl parameter, and
if login succeeds, get_isLoggedIn returns
true.
- The verifyUser method was removed.
The following examples show how to authenticate in the RTM
release.
var loggedIn = Sys.Services.AuthenticationService.get_isLoggedIn();
Sys.Services.AuthenticationService.login(userLogin, userPassword,
isPersistentCookie, customInfo, redirectUrl,
loginCompletedCallback,
failedCallback, userContext);
Sys.Services.AuthenticationService.logout(redirectUrl,
logoutCompletedCallback, failedCallback, userContext);
The following example shows the completed callback function
signature.
function loginCompleted(validCredentials, userContext, methodName) {..}
The following example shows the failed callback function
signature.
function loginFailed(errorObject, userContext, methodName) {..}
Detailed Server FX Changes
The ASP.NET AJAX server framework provides support for
component developers writing new server controls and extender
controls, as well as for page developers consuming those
controls.
The server framework also introduces the UpdatePanel
control and other controls that together support incrementally
updating an ASP.NET page or Web application with AJAX-type
behavior.
The main control in the Server FX is the ScriptManager
control and the closely related ScriptManagerProxy
control. These controls define an AJAX-style page by delivering
and managing the Client FX library scripts.
Configuration Section Entries
The following entries in the application's Web.config file are
required to provide a section handler for the
<system.web.extensions> section.
Note Some lines here are intentionally split for
formatting reasons.
<configuration>
<configSections>
<sectionGroup name="system.web.extensions"
type="System.Web.Configuration.
SystemWebExtensionsSectionGroup,
System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35">
<sectionGroup name="scripting"
type="System.Web.Configuration.ScriptingSectionGroup,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35">
<section name="scriptResourceHandler"
type="System.Web.Configuration.
ScriptingScriptResourceHandlerSection,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="false"
allowDefinition="MachineToApplication"/>
<sectionGroup name="webServices"
type="System.Web.Configuration.
ScriptingWebServicesSectionGroup,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35">
<section name="jsonSerialization"
type="System.Web.Configuration.
ScriptingJsonSerializationSection,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35"
requirePermission="false"
allowDefinition="Everywhere" />
<section name="profileService"
type="System.Web.Configuration.
ScriptingProfileServiceSection,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
requirePermission="false"
allowDefinition="MachineToApplication" />
<section name="authenticationService"
type="System.Web.Configuration.
ScriptingAuthenticationServiceSection,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral,
PublicKeyToken=31bf3856ad364e35"
requirePermission="false"
allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>
</configSections>
..
System.Web Configuration Section Entries
The following example shows entries in the application’s
Web.config file for the System.Web section.
Note Some lines here are intentionally split for
formatting reasons.
<system.web>
<pages>
<controls>
<add tagPrefix="asp" namespace="System.Web.UI"
assembly="System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</controls>
..
</pages>
<compilation debug="false">
<assemblies>
<add assembly="System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
</assemblies>
..
</compilation>
<httpHandlers>
<remove verb="*" path="*.asmx"/>
<add verb="*" path="*.asmx" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="*" path="*_AppService.axd" validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add verb="GET,HEAD" path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"
validate="false"/>
</httpHandlers>
<httpModules>
<add name="ScriptModule"
type="System.Web.Handlers.ScriptModule,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
</system.web>
System.Web.Extensions Section Entries
The following example shows the
<system.web.extensions> section of the
application’s Web.config configuration file.
Note Some lines here are intentionally split for
formatting reasons.
<system.web.extensions>
<scripting>
<webServices>
<!-- Uncomment this line to customize maxJsonLength and
add a custom converter
<jsonSerialization maxJsonLength="500">
<converters>
<add name="ConvertMe"
type="Acme.SubAcme.ConvertMeTypeConverter"/>
</converters>
</jsonSerialization>
-->
<!-- Uncomment this line to enable the authentication
service. Include requireSSL="true" if appropriate
<authenticationService enabled="true"
requireSSL= "true|false"/>
-->
<!-- Uncomment these lines to enable the profile
service. To allow profile properties to be retrieved
and modified in ASP.NET AJAX applications, you need
to add each property name to the readAccessProperties
and writeAccessProperties attributes.
<profileService enabled="true"
readAccessProperties="propertyname1,propertyname2"
writeAccessProperties="propertyname1,propertyname2"
/>
-->
</webServices>
<!--
<scriptResourceHandler enableCompression="true"
enableCaching="true" />
-->
</scripting>
</system.web.extensions>
Entries Required For IIS 7.0
The following section of the configuration file ensures that
your ASP.NET AJAX application will work under IIS 7.0.
Note Some lines here are intentionally split for
formatting reasons.
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules>
<add name="ScriptModule" preCondition="integratedMode"
type="System.Web.Handlers.ScriptModule,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</modules>
<handlers>
<remove name="WebServiceHandlerFactory-Integrated"/>
<add name="ScriptHandlerFactory" verb="*" path="*.asmx"
preCondition="integratedMode"
type="System.Web.Script.Services.
ScriptHandlerFactory, System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptHandlerFactoryAppServices" verb="*"
path="*_AppService.axd" preCondition="integratedMode"
type="System.Web.Script.Services.
ScriptHandlerFactory, System.Web.Extensions,
Version=1.0.61025.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"/>
<add name="ScriptResource"
preCondition="integratedMode" verb="GET,HEAD"
path="ScriptResource.axd"
type="System.Web.Handlers.ScriptResourceHandler,
System.Web.Extensions, Version=1.0.61025.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</handlers>
</system.webServer>
New Script Resource Handler, Compression, and
Crunching
Beta 2 change: A new script handler that can
reduce script size.
Beta 2 breaking change: The new script handler
must be registered in the Web.config file.
RC change: The ScriptResource.axd handler can be
configured for caching and compression. The handler now also
supports the resource substitution logic that is supported by the
WebResource.axd handler. You can add substitution references in
the embedded Web resources that are then handled by the
ScriptResource.axd handler.
Note: The substitution code
<%=WebResource() %> inserts a Webresource.axd
URL, and the <%= ScriptResource() %> code
inserts a ScriptResource.axd URL.
RC breaking change: The script compression
module is removed entirely; this is managed entirely by the
ScriptResource.axd handler. You must remove the reference in
Web.config to the script compression module.
Script compression means that the files are reduced in size,
which is done as a result of a request made to the handler.
Crunching scripts happens when scripts are built, and removes
whitespace and condenses local variable names to further reduce
the size of the script files.
In Beta of the RTM release, both debug and release scripts
that scripts are handled by ASP.NET are served through a module
that compresses them. In Beta 2, this task is managed by the new
ScriptResource.axd handler. When static, file-based scripts are
referenced, you will need to provide compression through IIS or
through some other compression utility is provided.
In Beta 2 of the RTM release, the new ScriptResource.axd
handler extracts and serves embedded script libraries and appends
the corresponding localized resources as appropriate.
Note The new script handler is required by the
framework and is a breaking change from the previous Beta
release. You must register the handler in the Web.config file, as
shown in the following example.
By default, the ScriptResource.axd handler caches scripts and
compresses scripts where feasible. You can control this behavior
by modifying the settings in the Web.config file as demonstrated
below.
Note The <system.web.extensions> section
requires the <configuration> sections entry in the
Web.config file. The ScriptResource.axd handler requires an entry
for the handler in the
<system.web><configuration> section.
<system.web.extensions>
<scripting>
..
<scriptResourceHandler enableCompression="false"
enableCaching="false" />
..
</scripting>
</system.web.extensions>
ScriptManager and ScriptManagerProxy Controls
Beta 2 change: Updates to script references have
been made to support localization for static, file-based script
references.
RC change: Script references have a new property
that can be used to control whether the notification script is
appended to assembly-based script libraries.
RC change: When a ScriptManager control
is used and script library URLs are rendered, the
ScriptResource.axd handler is used exclusively. The
WebResource.axd handler is used when there is no
ScriptManager instance on the page.
RC breaking change: Futures release scripts are
referenced using simpler names that no longer require the
Microsoft.Web.Resources.ScriptLibrary prefix.
RTM breaking change: The
ScriptLoadTimeout property of the ScriptManager
class has been removed. This property is no longer necessary,
because scripts are loaded through inline tags when an
asynchronous postback is not being performed.
RTM breaking change: By default, the
ScriptManager control infers its debug or release setting
from the current debug mode on the server. In the RTM release,
this value is inferred only from the debug setting in the
<compilation> section of the Web.config file in the
application root. It is not read from the configuration
hierarchy, as in previous releases.
RTM change: The ScriptManager control
provides script registration method overloads that take a
Page object as a parameter instead of a control. This
enables you to register scripts during asynchronous postbacks
without requiring a control in an UpdatePanel control.
The ScriptManager and ScriptManagerProxy
controls in the CTP release provided the means to define required
Client FX scripts such as the MicrosoftAjax.js script
library, and also provided a way to specify script references
with the Path or Name attributes. The following
example illustrates the use of the ScriptManager
control.
<atlas:ScriptManager runat="server" ID="ScriptManager">
<Scripts>
<atlas:ScriptReference ScriptName="AtlasUIGlitz" />
<atlas:ScriptReference Path="~/Scripts/Custom.js" />
</Scripts>
</atlas:ScriptManager>
Several key scenarios that were limited in the CTP release
have been addressed in the RTM release. In fact, the RTM release
opens up many options for the page developer. Changes made for
the RTM release include:
- The ScriptManager control still supports required
and optional scripts. For optional scripts, the main difference
from the CTP release is that there is no ScriptName
enum. This feature has been replaced by a more generic model
that allows third parties to deliver assembly-based Web
resource scripts. The following example illustrates the new
model and demonstrates the use of additional optional scripts
from the Futures release.
<asp:ScriptManager runat="server" ID="ScriptManager">
<Scripts>
<asp:ScriptReference
Name="PreviewScript.js" Assembly="Microsoft.Web.Preview" />
<asp:ScriptReference
Name="PreviewGlitz.js" Assembly="Microsoft.Web.Preview" />
<asp:ScriptReference Path="~/Scripts/Custom.js" />
</Scripts>
</asp:ScriptManager>
- The ScriptManager control allows you to reference
scripts from disk as static files in order to improve
performance. This applies to the Client FX scripts as well as
to custom scripts. This can be implemented with the
ScriptPath attribute (which is a global path). This
attribute points to a root path from which the originating
assembly name and its version are appended. It also means that
if you upgrade to a newer version of a component (for example,
System.Web.Extensions), the page code continues to work
but it references new script files. The following example
illustrates use of the ScriptPath attribute.
<asp:ScriptManager runat="server" ID="ScriptManager"
ScriptPath=”~/Scripts”>
<Scripts>
<asp:ScriptReference
Name="PreviewScript.js" Assembly="Microsoft.Web.Preview" />
<asp:ScriptReference
Name="PreviewGlitz.js" Assembly="Microsoft.Web.Preview" />
<asp:ScriptReference Path="~/Scripts/Custom.js" />
</Scripts>
</asp:ScriptManager>
Because the (root) global ScriptPath setting is
used, this model means that the script files defined in the
references are located in a final path that is determined
from the root plus the assembly and its version. In this
example, the following applies:
- The framework scripts are
~/Scripts/Microsoft.Web.Extensions/1.0.<build>.0/*.js.
- The optional preview scripts
are:~/Scripts/Microsoft.Web.Preview/1.0.0.0/*.js.
You can still define a local Path attribute on a
script reference to override the ScriptPath value. It
is also possible to force the use of an assembly for a given
script reference by using the IgnoreScriptPath
attribute.
- You can use the Path attribute to reference custom
scripts on disk, but you can also point directly to specific
Client FX scripts. If you customize the Client FX scripts, you
can reference your custom version and circumvent the framework
script directly, as shown in the following example.
<asp:ScriptManager runat="server" ID="ScriptManager">
<Scripts>
<asp:ScriptReference Name="MicrosoftAjax.js"
Path="~/Scripts/MicrosoftAjax2.js" />
</Scripts>
</asp:ScriptManager>
- The ScriptManager control allows you to specify Web
resource-based scripts. These can potentially be interpreted by
the Visual Studio “Orcas” tool for IntelliSense for
types and APIs within the script file. There are attributes for
the name and assembly on the ScriptReference tag.
- The ScriptReferences object supports a
NotifyScriptLoaded property that enables you to control
whether the notification script is appended to the script
library.
<asp:ScriptManager runat="server" ID="ScriptManager"
ScriptPath=”~/Scripts”>
<Scripts>
<asp:ScriptReference Name="Custom.Script.js" Assembly="Custom"
NotifyScriptLoaded=”false” />
</Scripts>
</asp:ScriptManager>
- The ScriptManager control supports a
ResolveScriptReference event that is raised for each
script reference, including the client framework scripts. You
can handle the ResolveScriptReference event to
dynamically change the script reference, such as pointing it to
another location. For example, you can redirect the script
reference to a server geographically closer to the requestor
based on the incoming IP address, for performance reasons. The
following example illustrates how to handle the
ResolveScriptReference event.
<asp:ScriptManager runat="server" ID="ScriptManager"
OnResolveScriptReference="ResolveScriptReference">
..
</asp:ScriptManager>
<script runat="server">
protected void ResolveScriptReference(object sender,
ScriptReferenceEventArgs e) {
e.Script.Path = “~/newLocation/” + e.Script.Name;
...
}
</script>
Handling Debug and Release Scripts
RTM breaking change: By default, the
ScriptManager control infers its debug or release setting
from the current debug mode on the server. In the RTM release,
this value is inferred only from the debug setting in the
<compilation> section of the Web.config file in the
application root. It is not read from the configuration
hierarchy, as in previous releases.
In the CTP release, the ScriptManager control could
specify a reference to debug versions of scripts instead of
release versions. As noted earlier, the main difference between
the debug and release scripts was that the release scripts remove
unnecessary whitespace. The determination to serve the debug or
release version was based on the debug=true setting in the
Web.config file.
Based on customer feedback, the RTM release uses a new model
that allows the ScriptManager control to separate server
debugging from client debugging. If the ScriptManager
control's ScriptMode property is set to Auto or
Inherit, by default the ScriptManager control uses
the debug setting of the <compilation>
element in the application’s Web.config file. To enable you
to specify debug mode for scripts independently, the
ScriptMode property can be set to force debug or retail
mode.
The ScriptManager control infers the debug versions of
script references based on a naming convention for script files
that are on disk or embedded as Web resources in an assembly. You
always reference the release versions of scripts declaratively or
programmatically. The ScriptManager control determines
whether to send debug or release versions based on current
settings, and handles fallback if the debug versions of
assembly-based scripts do not exist.
When you register script references with the
ScriptManager control, you can set a ScriptMode
property on individual references, which overrides the value on
the ScriptManager control. The default value of the
ScriptMode property for a script file reference depends on
whether it is a file-based or an assembly-based script reference.
For example, for a file-based script, the ScriptMode
property is set to release by default. This means
references never assume the existence of debug script files.
If the script reference is assembly-based, the
ScriptMode property is set to inherit, which means
the property gets its value from the ScriptManager
control. This means that by default, the ScriptManager
control uses the file name of the script reference to determine
whether to load a debug script; if so, it checks the assembly for
the script and performs fallback behavior if the script does not
exist.
In the RTM release, both release and debug scripts are
compressed by default through the script resource handler. In the
RTM release, release scripts are also "crunched."
Script and Other Resource Registration APIs
RTM change: The ScriptManager control has
new APIs that enable you to register scripts during an
asynchronous postback. These APIs are overloads of existing
methods, but instead of taking a Control instance as a
parameter, they take a Page instance. This allows you to
register scripts without the need to have a control and to
register scripts independently of an UpdatePanel being
updated. The methods with these new overloads are:
- RegisterArrayDeclaration
- RegisterClientScriptBlock
- RegisterClientScriptInclude
- RegisterClientScriptResource
- RegisterHiddenField
- RegisterOnSubmitStatement
- RegisterStartupScript
As explained in the UpdatePanel section, in the RTM
release, the ScriptManager control includes new APIs for
registration of scripts and other resources, allowing the
ScriptManager and the client pageRequestManager
control how to track changes in UpdatePanel partial-page
postbacks.
In addition, new controls, including extenders controls that
leverage the Client FX in the RTM release, will define their
script libraries and their client object instance scripts with
the ScriptManager control after they have registered
themselves with ScriptManager.
Extender controls allow you to augment an existing server
control with new functionality or behavior by attaching a client
behavior to the control. In the CTP release, you used a single
extender control and you set extender control properties which
mapped to the target server control, as in the following
example.
<asp:TextBox runat="server" ID="City" />
<br/>
<asp:TextBox runat="server" ID="CountryOrRegion" />
<atlas:AutoCompleteExtender runat="server" ID="AutoComplete1">
<atlas:AutoCompleteProperties TargetControlID="City"
Enabled="True" ServicePath="AutoCompleteWebService.asmx"
ServiceMethod="GetCompletionList" />
<atlas:AutoCompleteProperties TargetControlID="CountryOrRegion"
Enabled="True" ServicePath="AutoCompleteWebService.asmx"
ServiceMethod="GetCompletionList" />
</atlas:AutoCompleteExtender>
In the RTM release, based on community feedback, this model
has been changed to simplify the concept. In the RTM release,
extenders simply map to their target control directly, and
multiple extenders can target the same control. There are no
separate extender properties. The following example illustrates
this. (Multiple extenders for a control are not shown here.)
Note The RTM release does not include an
AutoCompleteExtender control; this control is the ASP.NET
AJAX Control Toolkit.
<asp:TextBox runat="server" ID="City" />
<asp:AutoCompleteExtender ID="CityAutoCompleteExtender" runat="server"
TargetControlID="City" Enabled="True"
ServicePath="AutoCompleteWebService.asmx"
ServiceMethod="GetCompletionList" />
<br/>
<asp:TextBox runat="server" ID="CountryOrRegion" />
<asp:AutoCompleteExtender ID="CountryRegionAutoCompleteExtender"
runat="server”
TargetControlID="CountryOrRegion"
Enabled="True" ServicePath="AutoCompleteWebService.asmx"
ServiceMethod="GetCompletionList" />
Extender Controls and the Component Developer
Beta 2 change: Extender controls and script
controls register themselves in the PreRender stage.
RC change: The base class calls the
ScriptManager control's RegisterScriptDescriptors
method during its Render method. This means that extenders
can now be used in scenarios where the Render method is
not called, such as in closed Web Parts. If you create controls
instead that implement the IExtenderControl interface, you
must add a call to the RegisterScriptDescriptors method in
your control's Render method.
RC change: A method has been added that enables
controls and extenders to register their client components as
disposable objects without requiring a DOM element. This is
performed automatically in ScriptDescriptor types.
In the CTP release, component developers were able to use the
ExtenderControl base class and its
ExtenderControlProperties class. The developer was
responsible for generating the client script for the associated
behavior, either as JavaScript or xml-script, and rendering it
using the ScriptTextWriter object that was passed to the
extender's RenderScript method. Component developers
registered their library scripts in a particular control
life-cycle event, such as the PreRender event.
Based on feedback and again to reduce complexity and enable
extensibility in the future, we implemented a new model. In the
RTM release model, component developers use an
ExtenderControl class directly. IScriptControl and
IExtenderControl interfaces are available and can be
implemented by component developers on their controls directly,
if needed.
Extender controls continue to register with the
ScriptManager control. However, they are called by the
framework to provide their library scripts and their new
ScriptDescriptor types, instead of the old model where the
control developer rendered them at a point in the control life
cycle chosen by the developer. ScriptDescriptor types map
indirectly to the Component, Behavior, and
Control client types; these abstract the generation of the
script for the client object, making the generation of the client
object a simple matter.
Note In the Beta version of the RTM release,
controls could register with the ScriptManager control in
the Init stage. In Beta 2, this must be done in
PreRender.
Note If you create a control using the
IExtenderControl interface directly, you must call the
ScriptManager.RegisterScriptDescriptors method in your
Render method.
In this model, the server control does not require knowledge
of the form of script to render, which allows future
extensibility and support. The following simple example
demonstrates use of ScriptDescriptor types in the RTM
release.
protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors
(Control targetControl) {
ScriptBehaviorDescriptor descriptor =
new ScriptBehaviorDescriptor("Sample.UI.BorderBehavior",
targetControl.ClientID);
if (!Color.IsEmpty) {
descriptor.AddProperty("color", ColorTranslator.ToHtml(Color));
}
if (Style != BorderStyle.NotSet) {
descriptor.AddProperty("style", Style.ToString());
}
if (!Width.IsEmpty) {
descriptor.AddProperty("width", Width.ToString());
}
yield return descriptor;
}
protected override void GetScriptReferences() {
ScriptReference reference = new ScriptReference();
Reference.Path = ResolveClientUrl(
"~/ScriptControls/BorderBehavior.js"));
yield return reference;
}
This example shows use of the simple AddProperty API on
a ScriptDescriptor type to set property values on the
client object. Notice also that you use the
ScriptReference type to pass a particular script
reference, which in this case is a static URL instead of a Web
resource-based reference (or similar).
RC Change: The ScriptControl base class
has been added. This class enables component developers to create
controls that implement the IScriptControl interface.
IScriptControl types are similar in concept to the
IExtenderControl shown above. In the control's
Render method, the control calls the
ScriptManager.RegisterScriptDescriptors method, as
mentioned previously.
Note If you create a control using the
IScriptControl interface directly, you must call the
ScriptManager.RegisterScriptDescriptors method in your
Render method.
RC Change: A ClientID property has been
added to the ScriptComponentDescriptor object. You should
use this property to reference this client object (for example,
if you generate a reference to the object) in another clients
object.
RC change: The ScriptControlDescriptor
class throws an exception in the ID property set accessor
method. The ID property is defined exclusively by the ID
of the DOM element.
RC change: The ScriptBehaviorDescriptor
object returns the value of the ID property through the
ClientID property if the ID is non-empty.
Otherwise, it returns the value of
<ElementID>$<Name>.
RC change: The AddScriptProperty method
has been added to enable you to set a property that is a script
expression.
RTM change: If you set the Name property
to a non-empty value, the value will be propagated to the
$create function.
The ExtenderControl and ScriptControl base
classes (which implement the IExtenderControl and
IScriptControl interfaces) register themselves with the
ScriptManager control during the PreRender stage.
The ScriptManager control calls on the interface members
on these controls to obtain their script references and script
libraries, which define the client objects for the control.
The controls must also call the
ScriptManager.RegisterScriptDescriptors method during
their Render stage so that the ScriptManager will
call back to obtain the script descriptors. (This ensures that
the client object is created only when a referenced DOM element
exists.) Script descriptors are used to create an instance of the
client component in the client, as is done with the
$create function.
If you are a component developer, you use the script
descriptor types to create component, behavior, and control types
that run in the client. Specific script descriptors are available
and offer the following methods:
- AddProperty: Sets a property (calls the get and set
accessor functions) of the client object.
- AddElementProperty: Sets a property of a client
object, which is a reference to a DOM element. As a result, a
$get method for the property is defined in the
client.
- AddEvent: Sets an event handler (calls the
add_ and remove_ functions) of the client
object.
- AddScriptProperty: Sets a script expression to a
property of a client object.
- AddComponentProperty: Sets a client object reference
to a property of a client object.
Scenarios that use the UpdatePanel control are key
scenarios in ASP.NET AJAX Extensions. We received much customer
feedback on this control, on the UpdateProgress control,
and on the functionality of both. We made a number of changes to
improve partial-page rendering and to support building controls
compatible with the UpdatePanel control. We also
implemented a rich event model for the asynchronous postback life
cycle to allow you to customize client handling of the
update.
Beta 2 change: The ScriptManager control
provides a SupportsPartialRendering property whose initial
values are derived on the server from browser capabilities. For
browsers that do not support partial-page rendering,
UpdatePanel controls will degrade to use regular
postbacks.
Beta 2 change: The ScriptManager control
provides a compatible SetFocus API that enables developers
to manage the focus in the browser.
Beta 2 change: The ScriptManager control
provides a RegisterDispose method that can be called to
register client components as disposable objects. This means that
components do require an associated DOM element to work with
UpdatePanel controls.
RC change: A RegisterDispose method has
been introduced in the ScriptManager class that enables
controls and extenders to register their client components as
disposable objects without requiring a DOM element. This is
performed automatically in ScriptDescriptor types.
RTM change: See previous section for a
description of new overloads for the static script registration
methods that take a Page object instead of a
Control object as a parameter.
In the RTM release, the ScriptManager control has an
EnablePartialRendering property that is true by
default. This reduces the number of steps required to define an
asynchronous postback with an UpdatePanel control.
The ErrorTemplate property of ScriptManager has
been removed in the RTM release to reduce the control's
complexity. The error handling model is now more flexible, such
as creating a new, independent server control. Alternatively, you
can now add error handling using the
AsyncPostBackErrorMessage property of
ScriptManager. It sets only the default error message. To
customize the message dynamically, you can handle the
AsyncPostBackError event.
ScriptManager now exposes an
AsyncPostBackTimeout property to control the timeout
duration during asynchronous postbacks.
The ScriptManager control supports new registration
method for resources that might be required by server controls.
These methods enable support for UpdatePanel scenarios and
reduce the complexity of the CTP release version of the
UpdatePanel control. Resources can include scripts,
styles, hidden fields, and so on. The script registration methods
correspond to the ClientScriptManager methods. They accept
a control instance as a parameter, so that the control that
registered the script can be tracked in case it is contained
within an UpdatePanel server control.
Dynamic UpdatePanel Controls
There are two main scenarios for adding UpdatePanel
controls to a page dynamically, and these have been improved in
the RTM release. The scenarios for using dynamic
UpdatePanel controls are:
- Control developers can add UpdatePanel controls to
their custom composite controls. This enables asynchronous
postbacks from within the custom control if the page has a
ScriptManager control with its
EnablePartialRendering property set to true. It
also provides the ability to fall back to regular postbacks if
a ScriptManager control does not exist on the page.
- Page developers can add UpdatePanel controls to
templates of other controls.
The following code demonstrates the use of an
UpdatePanel control in a custom control.
protected override void CreateChildControls() {
base.CreateChildControls();
ScriptManager sm = ScriptManager.GetCurrent(Page);
Control parent;
Control container;
if (sm == null || !sm.EnablePartialRendering) {
// If not doing partial rendering, use a
// dummy control as the container.
parent = container = new Control();
}
else {
// Create an UpdatePanel control.
UpdatePanel up = new UpdatePanel();
// Instead of adding child controls directly to
// the UpdatePanel control, add them to its
// ContentTemplateContainer.
container = up.ContentTemplateContainer;
parent = up;
}
AddDataControls(container);
Controls.Add(parent);
}
Client Events During Asynchronous Postbacks
In the CTP release, the client PageRequestManager
object performs asynchronous postbacks by creating an
XMLHttpRequest object and processing the response. In the
RTM release, the PageRequestManager object provides
asynchronous-postback life-cycle events so you can customize
handling of the request and response. The following client events
are available and have corresponding event arguments that provide
additional information.
- initializeRequest: You can use this event to
cancel a new asynchronous postback request that is about to be
made. The event also enables you to evaluate the postback
source and do any additional required work. The event args are
of type InitializeRequestEventArgs.
- beginRequest: You can use this event for tasks such
as displaying progress. Begin the display during this event and
hide it in the endRequest event. The event args are of
type BeginRequestEventArgs.
- pageLoading: You can use this event to perform
additional handling for the panels being updated or deleted,
such as running clean-up code. You can also inspect any
additional data sent from the server for performing
customizations. The event args are of type
PageLoadingEventArgs.
- pageLoaded: This event is similar to
pageLoading, but gives you information about any
additional UpdatePanel controls that were created as a
result of the asynchronous postback. The event args are of type
PageLoadedEventArgs.
- endRequest: You can use this event to customize
error handling and to process additional data from the server.
You can also use it to hide the UpdateProgress control.
The event args are of type EndRequestEventArgs.
Developing Controls Compatible with the UpdatePanel
Control
RTM breaking change: In the final release of ASP.NET 2.0 AJAX Extensions 1.0,
the ASP.NET AJAX control validators that were included in the Beta and RC versions to be compatible with
asynchronous postbacks, were removed. This avoids conflicts with a new set of validators that will be
shipped in a .NET Framework update in the near future.
Application developers who require validators in their deployed applications
can read the blog post titled
ASP.NET
AJAX Validators for information about
removing the validators and for workarounds to using the validators.
The blog post includes the source code for the validators, which
developers can use in their applications if required.
When the .NET Framework update is available, you should install it as soon as
possible to make the updated validators available to hosted applications.
In the CTP release, the UpdatePanel control processed
many objects being rendered, including some that were not within
the UpdatePanel control, and then tried to retrofit all
changes in the page. This made some controls incompatible with
the UpdatePanel control. For example, in the CTP release,
ASP.NET validator controls did not work well inside an
UpdatePanel if they were dynamically added or removed,
such as in a Wizard control that validates user input at
each step.
The model is improved in the RTM release. To send scripts or
data to the client, you register them with the
ScriptManager control, the way you register script
libraries. The following example demonstrates a custom control in
the RTM release that is compatible with the UpdatePanel
control.
protected override void OnPreRender(EventArgs e) {
base.OnPreRender(e);
Control control = FindControl(_controlID);
// Register scripts with new ScriptManager APIs.
// The scripts hook up new PageRequestManager events.
string script = String.Format(
CultureInfo.InvariantCulture,
@"var {0}_hover = new Microsoft.Samples.HoverExtender(document.getElementById('{1}'), '{2}');
{0}_hover.attach();
",
ClientID,
control.ClientID,
ColorTranslator.ToHtml(BackgroundColor));
ScriptManager.RegisterClientScriptInclude(
this, typeof(HoverExtender), "HoverExtenderScript",
ResolveClientUrl("~/ScriptLibrary/HoverExtender.js"));
ScriptManager.RegisterStartupScript(
this, typeof(HoverExtender), ClientID, script, true);
}
Sending Additional Data to the Client
A scenario not easily accomplished in the CTP release was to
update controls outside an UpdatePanel control with data
received from the server during an asynchronous postback. The RTM
release addresses this by providing a method of the
ScriptManager class that allows you to register a data
item.
Consider a client timer control whose interval or
enabled property value is changed at run time in server
code, but that is not contained in an UpdatePanel control.
In the CTP release, making this run-time change was not
possible.
In the RTM release, the ScriptManager exposes a
key-value dictionary object on the server that you can update and
then register using the RegisterDataItem method. The
dictionary is then sent to the client and is available in the
pageLoading, pageLoaded, and endRequest
events by calling the eventArgs.get_dataItems( )
method.
The following example illustrates how to make use of the data
item.
// Server control code.
...
Public int interval {
get {…}
set {
_data = value;
...
}
}
void PreRender() {
ScriptManager sm1 = ScriptManager.GetCurrent(Page);
if (sm1 != null && sm1.IsInAsyncPostBack) {
ScriptManager.RegisterDataItem(this, _data.ToString());
}
// The control also needs to register script to handle the
// endRequest event on the client and retrieve this value.
// The script below adds a handler for the current instance
// of the PageRequestManager object and calls the
// get_dataItem() method from eventArgs.
ScriptManager.RegisterClientScriptBlock(this, this.GetType(),
key, script)
}
Custom Error Handling and Redirection
In the CTP release, there was no way to control error
handling, and custom error settings were not honored. The RTM
release addresses these issues.
The ScriptManager object exposes an
AllowCustomError property. When this property is set to
false, the ScriptManager object overrides custom
error redirects and instead sends the error to the client, where
you can display error information without redirecting the user to
another page.
The RTM release handles redirection through the addition of a
Redirect module. Cross-page posting scenarios are
therefore handled now in the RTM release.
In the CTP release, the ScriptManager control exposed
the ControlValueTrigger and ControlEventTrigger
types in the triggers collection for binding triggers to controls
on the page. In the RTM release, these objects have been combined
into a single AsyncPostBackTrigger object to remove the
confusion over the two trigger types.
In response to customer feedback, we added the ability to
perform full (synchronous) postbacks from inside an
UpdatePanel control using the PostBackTrigger
object. The Trigger object can also now refer to controls
that implement the IPostbackEventHandler,
IPostBackDataHandler, or INamingContainer
interfaces.
AsyncPostBackTrigger controls can cause the
UpdatePanel control to be updated during asynchronous
postback when the trigger is raised. The triggers can point to
controls outside the UpdatePanel, or up the control
hierarchy to the parent control. When a control that is a naming
container is used as a trigger, all of its child controls that
cause postback behave as triggers.
The following example shows how to use the
AsyncPostbackTrigger object declaratively.
<asp:Button runat=”server” id=”Button1” Text=”Go” />
<asp:UpdatePanel ID="UP1" UpdateMode="Conditional" runat="server">
<ContentTemplate>...</ContentTemplate>
<Triggers>
<asp:AsyncPostbackTrigger ControlID="Button1" />
</Triggers>
</asp:UpdatePanel>
A PostBackTrigger control causes referenced controls
inside an UpdatePanel control to perform regular
postbacks. These triggers must be children of the affected
UpdatePanel.
The RTM release features an improved UpdateProgress
control with additional functionality to customize showing the
UpdateProgress control only if the asynchronous postback
takes longer than a specified time interval. You can further
manage how the UpdateProgress control renders to determine
whether the control takes up white space on the page when hidden,
similar to setting the DisplayMode property of ASP.NET
validators to "dynamic". For adding cancel functionality to the
progress UI, you add a few lines of code; this has changed from
the CTP.
The following example shows how to configure the
UpdateProgress control to display show only if the request
takes longer than half a second (500 milliseconds).
<asp:updateprogress runat=server ID="Progress1" DisplayAfter="500">
<ProgressTemplate>
<b>Working on request...</b>
<input type="button" id="abortButton" onclick="abortPB()"
value="Cancel" />
</ProgressTemplate>
</asp:updateprogress>
<script type="text/javascript" > function abortPB() {
var obj = Sys.WebForms.PageRequestManager.getInstance();
if (obj.get_isInAsyncPostBack()) {
obj.abortPostBack();
}
}
</script>
RTM change: In conjunction with the release of
the RTM release of ASP.NET AJAX Extensions, the Futures release
has been modified. The AutoCompleteExtender,
AutoCompleteBehavior, PopupBehavior, and
HoverBehavior types have been moved to the ASP.NET AJAX
Control Toolkit. The Futures release works in conjunction with
the RTM release. This section lists the main differences between
Futures release features and the corresponding features in the
CTP release.
The Futures release has moved features to new namespaces both
in the client and the server to avoid any confusion with the RTM
release. In this case, developers using the CTP release will be
required to update existing Web.config files with new entries if
their applications use features that are defined in the Futures
release. The following example shows a snippet of a Web.config
file that illustrates these changes.
<system.web>
...
<pages ...>
<controls>
<add namespace=”Microsoft.Web.Preview.UI”
assembly=”Microsoft.Web.Preview” tagPrefix=”atlas” />
<add namespace=”Microsoft.Web.Preview.UI.Controls”
assembly=”Microsoft.Web.Preview” tagPrefix=”atlas” />
</controls>
</pages>
</system.web>
You can add the assembly for the Futures scripts and server
features to the Bin folder of a Web application, as was the case
in the CTP.
Note In Beta2, the assembly name has changed from
Microsoft.Web.Atlas.dll to Microsoft.Web.Preview.dll.
In the CTP release, you simply needed to add the
ScriptManager control to a Web page and by default the
core CTP functionality was included (Atlas.js). However, some
script files were optional, such as the AtlasUIGlitz.js file. You
manually entered these as script references as part of the
ScriptManager control, or defined them in the
<references> section in xml-script.
In the RTM release, to consume the Futures features you need
to add explicit script references to the ScriptManager
control. The following example shows how all script files are
defined in the Futures release.
Note The order of registration is important here,
given the dependency chain.
<asp:ScriptManager runat=”server” id=”ScriptManager1”>
<Scripts>
<asp:ScriptReference Assembly="Microsoft.Web.Preview"
Name="PreviewScript.js"/>
<asp:ScriptReference Assembly="Microsoft.Web.Preview"
Name="PreviewGlitz.js"/>
<asp:ScriptReference Assembly="Microsoft.Web.Preview"
Name="PreviewDragDrop.js"/>
</Scripts>
</ScriptManager>
Client-based and Server-based Types
The types defined in the Futures scripts have been moved from
the Sys.* namespace to their own separate
Sys.Preview.* namespace. This ensures that a distinction
is made in the functionality. Developers previously using
features during the CTP that have moved to the Futures scripts
may need to update their JavaScript code. An example of such a
change is the Sys.Services.Components.Profile component,
which is now Sys.Preview.Services.Components.Profile.
Similarly, developers who are using server features such as
controls and extenders in the CTP that have also moved to the
Futures release will need to update the Web.config file entries
for a new namespace definition. The CTP defined server-types
under the Microsoft.Web.* namespace. This is now
Microsoft.Web.Preview.*. An example of this is the
Microsoft.Web.UI.Controls.DragOverlayExtender, which now
is
Microsoft.Web.Preview.UI.Controls.DragOverlayExtender.
Xml-script continues to work in the Futures release, but has
some changes that result from the effects of the RTM release. It
also features some improvements in declarative xml-script.
Note Xml-script tags are case insensitive. However,
specific property attributes and their values are case sensitive
and might therefore require modifications in your
applications.
Xml-script tag names follow the type name directly. The
following built-in tags in the CTP have changed in the Futures
scripts:
<opacity .../>
<layout .../>
<autoComplete .../>
<setProperty .../>
<invokeMethod .../>
<serviceMethod .../>
<postback .../>
<select .../>
In the Futures scripts, these tags are:
<opacityBehavior .../>
<layoutBehavior .../>
<autoCompleteBehavior .../>
<setPropertyAction .../>
<invokeMethodAction .../>
<serviceMethodRequest .../>
<postbackAction .../>
<selector .../>
Xml-tags are still scoped to the built-in script prefixes; in
addition, support for custom prefixes has been improved to allow
the following syntax. This allows a comma-separated namespace
notation.
<script type="text/xml-script">
<page xmlns ="http://schemas.microsoft.com/xml-script/2005"
xmlns:prefix="JavaScript: Sys.UI,Sys">
<components>
...
</components>
</page>
</script>
Creating Declarative Bindings
Bindings are moved from the CTP to the Futures scripts and can
be supported at any level in the markup, without being nested
within a particular control. When nested, bindings infer their
context or source from their parent. The following example shows
the use of the same binding in the CTP and the Futures
releases.
<script type="text/xml-script">
<page xmlns "http://schemas.microsoft.com/xml-script/2005">
<components>
<textbox id="Name" />
<label id="FirstName">
<bindings>
<binding dataContext="Name" dataPath="text"
property="text"/>
</bindings>
</label>
</components>
</page>
</script>
In the Futures scripts, the bindings propertyKey
attribute supports a dot notation, allowing you to specify
sub-properties. In cases where properties have been removed from
the base Control type (such as visible), you can
reference them as sub-properties. The following example shows the
setting of a style property on the element that is associated to
the Button control.
<script type="text/xml-script">
<page xmlns="http://schemas.microsoft.com/xml-script/2005"
xmlns:prefix="javascript: Sys.UI,Sys">
<components>
<textbox id="Name" />
<label id="FirstName">
<bindings>
<binding dataContext="Name" dataPath="text"
property="text"/>
</bindings>
</label>
<button id="button2">
<click>
<setPropertyAction target="text1" property="element"
propertyKey="style.borderColor" value="black" />
</click>
</button>
</components>
</page>
</script>
This example also shows the use of an action,
setPropertyAction, that is invoked as a result of the
click event on the Button control.
In the CTP you could add script references to xml-script
declaratively. This is not currently supported in the Futures
release.