Introduction
To get an overview of Web Application environment and its constraints with reference to ASP.NET AJAX, please read my previous article: A Note on Web Application with reference to ASP.NET AJAX.
As discussed in that article, we know that a web application is stateless in nature, and it works in a disconnected mode, i.e., the Web Server always handles an incoming client request as new, without any continuity with an earlier one. Keep this in view while we try to understand the underlying concepts in the Event based ASP.NET Web Form Programming Model.
The Event based programming model as such is conceptualized from the famous Hollywood principle: "Don't call us, we'll call you" (Hollywood Principle). It is a very useful paradigm, and assists us in the development of code which is easy to understand (with high cohesion) and easy to maintain (low coupling). How is this achieved? The key to making this possible is to sacrifice the element of control as was there in traditional program flows. So in our case, instead of making the application drive the system (which includes the ASP.NET runtime), the ASP.NET runtime drives our application.
To make this orchestration (using the Event based programming model) successful and to integrate seamlessly with the ASP.NET framework, we, as developers, should therefore have to write code that follows some conventions and requirements of the framework (in this case, ASP.NET), and that is what we are going to cover in this article.
I am not going to cover the rigorous details, like the Document Object Model (DOM) and Event propagation within DOM (event bubbling) etc. But I will try to illustrate what ASP.NET designers wanted to achieve and how we can gain the benefits by using this model. This article looks at the server side as well as the client side Event models, and then using an ASP.NET server control, we will walkthrough from the client to the server and back (round trip in post-back).
I have used the Fiddler tool to intercept what goes through wire. We will analyze this data to get an inside view of the payload which flows between the client and the server in each round trip of the page. Please note that we are not going into the ASP.NET working internals, describing each and every published file for a project, rather we discuss everything at a conceptual level.
Overview
In the ASP.NET Web Form Model, a page consists of two parts: visual elements (HTML, Server Controls, and Static Text, CSS, JavaScript etc.) and the page's programming logic. Microsoft's IDE (Visual Studio) stores each of these two distinct parts in two separate files. The visual elements are created in an .aspx, and the code is in a separate class file, called the code-behind class file (.aspx.vb or .aspx.cs). Of course, as you will see and we will discuss, it is a better practice to keep the CSS styles and JavaScript code for page behaviors within the browser, outside the .aspx for better readability and reuse. You will find this approach in the enclosed sample.
As just discussed above, although a Web Form page consists of two separate files, they together form a single unit when our application is run. The code-behind class files for all Web Forms in a project are compiled into a dynamic-link library (.dll) file produced by the project. The Web Form's .aspx page file is also compiled, but it is done in a different way. The .dll file is run at the server whenever a Web Form page is requested. At run time, this .dll file processes the incoming request and responds by creating dynamic output and sending it back to the browser or client device.
If the page contains server controls, as in the sample, the derived page class acts as a container for the controls. Instances of the controls are created at run time on the server, and the Page
class then renders the output for the browser or the client device.
This Page
class, in effect, models the entire Web Form page. The Page goes through a series of processing stages (termed as the Page Life Cycle). These include initialization, instantiating controls, restoring and maintaining state, executing event handler code, and finally, rendering. Similar Page Life Cycles are also followed by server controls (you need to know this when developing custom server controls) which are contained inside the Page.
The Page
class has a unique stage 'render' - that occurs towards the end of the Page Life Cycle, when output is generated. Note that 'render' is a processing stage, not an Event. Before rendering, the View State (the page View State is managed by ASP.NET in the form of a hidden <input>
control, and is used in persisting state/information over a page roundtrip to the server) is saved for the page and all the controls. During the rendering phase, the page calls the Render
method for each control, providing a text writer that writes its output.
It is important to note that the Page
class performs these steps each time the page is called. The page is initialized, processed, and disposed of every time a round trip to the server occurs.
Within each stage of the life cycle of a page, the page raises events that we can handle to customize and run our own code. For control events, we bind the event handler to the event, either declaratively using attributes such as "onclick
", or in code.
The relationship between .aspx, .aspx.cs, or .aspx.vb and ASP.NET runtime classes is illustrated by the following figure. As an example, a new class named _Default
is derived from System.Web.UI.Page
.
public partial class _Default : Page
The .aspx page file in turn inherits from the derived _Default
class.
Fig. 1
Because the .aspx file is compiled dynamically when a user browses the page, its relationship to the class file is established with script
directives at the top of the page. In an ASP.NET Web Form, the '@Page
' directive (or '@Control
' in user control files) contains attributes that specify the relationship of the .aspx file and its code-behind file. For example:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" EnableEventValidation="false" %>
The server loads an ASP.NET page every time it is requested, and then unloads it after the request is completed. The page and the server controls it contains are responsible for executing the request and rendering the HTML back to the client.
Although the communication between the client and the server is stateless and disconnected, the primary goal of this ASP.NET Web Form model is that the client must experience similar to that of a continuously executing stateful process on his own desktop. The other goal of this model is to help developers like us in building Web Applications quickly in a Rapid Application Development IDE like Microsoft Visual Studio.
The illusion of stateful continuity is created by the ASP.NET Page framework and by the Page and its controls. On postback, a control must behave as if it is starting from where it was left off at the end of the previous web request.
The designers of the ASP.NET Page framework at Microsoft make it relatively easy to perform state management, but Control and Page developers like us must be aware of the control execution sequence to achieve the effect of continuity. This is what we need to know from the ASP.NET Page Life Cycle as a sequence of Events while the Web Form page is being processed by the ASP.NET runtime on the Web Server.
Event Based Programming in ASP.NET
First, let us discuss a little background. The event model was popular in Windows Desktop application development in Visual Basic and Visual C++ using MFC. This is quite different from the sequential procedure based model (represented by a Flow Chart). In the Event model, each application state is an object, and Event as a trigger moves one application state to another state. A state as an object moves our focus from the flow of control to the properties of the state. The flow is relegated to an Event (trigger) that makes transitions from one state to another. Knowing the advantages of this approach, Microsoft has extended this model and introduced Server Controls as well as Page based Web Form Programming model to ASP.NET. In this model, the application developers need not be concerned with the details of how to gather input from the User Interface (GUI) or render output (for example, HTML) to the User Interface. Instead, we should focus on application specific behaviors in the Event handlers attached to the UI components that receive Events or triggers from the ASP.NET runtime. As explained earlier, traditionally, Events are used as a means of decoupling among various components. In the case of ASP.NET for example, the functionality of a UI control, say, a Button, can be integrated with another Web application without requiring any change in the UI control itself (by drag and drop in Visual Studio designer).
A web application is a client server application, where the client is separated from the server over the internet. For the Event handler code which runs on the server to react to the changes the user makes on the Web Form in the browser, the control must shift execution from the client browser back to the Web Server. In ASP.NET, server controls such as asp:Button are responsible for handling this by generating a form postback when it is clicked. We will see all these details shortly as we progress through this article.
Event and Event Handling
An Event is a notification that occurs when something of concern happens. Events allow an object (sender) to notify other objects (receivers) that something special has happened. A good example of an event is a button click.
Essentially, an event handler is similar to a callback. Only a finer difference does exist between them. To look at this angle, an Event is sort of an anonymous broadcast whereas a callback is a sort of a handshake.
When we write an Event handler for the Click event of an ASP.NET Button, we are really writing the implementation for a callback method. However, we are not required to explicitly call the Event handler. Instead, the Page
class of the ASP.NET Web Forms framework acts as a notification source because it automatically executes our Event handler method at exactly the right time (the control of the program execution flow lies with the ASP.NET run time).
Now, let us pay our attention to the Event handling mechanism. Instead of calling a function whose name is known at compile time, the component calls a function we provide at run time (late binding). Raising or firing an Event means calling the handler. To make this happen, the Event (or notification) receiving the component first gives the Event source component a pointer to its Event handler code, a process named as Registration.
Events & Delegates
To handle Events, ASP.NET Designers from Microsoft have introduced a new type as Delegate. A Delegate is often defined as an object oriented function pointer. A Delegate provides the necessary layer of indirection between an Event Publisher and an Event Subscriber. By design, the publisher of an Event has absolutely no knowledge of any of the subscribers. Consequently, it is the job of the subscribers to register or un-register themselves with the publisher of an Event. As a consequence of this, Delegates always return void
, as the Event Publisher can not do anything from the return values from the Event Subscribers.
As described above, the binding between the Event on the publisher and a specific method, that is, an Event handler on the subscriber - is done using an Event Delegate. The ASP.NET page framework automatically connects to (or wires up) the appropriate Delegate instances at run time for these methods. When we declare a Delegate, what we actually do is define a class.
The necessary steps are done here by the compiler when we declaratively bind Events with our custom Event handlers:
- Declare a Delegate object with a signature that exactly matches the method signature of the Event handler.
- The Delegate object is referenced using the keyword '
event
', so define that.
- Define the Event handler method.
- Create a Delegate object and plug in the method that we want to encapsulate and register with the object that will fire the Events.
public delegate void OnClickEventHandler (object sender, EventArgs e);
public event OnClickEventHandler Click;
protected virtual void OnSubmit (object sender, EventArgs e) { ... }
and OnInit
:
this.Click += new EventHandler(this.OnSubmit);
Click
is the name of the Event. This Event is of the OnClickEventHandler
type, meaning that all receivers of the Event notification must supply a callback method whose prototype matches that of the OnClickEventHandler
delegate. As shown earlier in an .aspx page, if we keep the property AutoEventWireup="true"
, then we do not have to write the necessary plumbing code as shown just above.
Introduction to Example Projects
There are two examples using the same application, both use the ASP.NET server controls Button
and GridView
.
- One without Partial Rendering, i.e., without the
ScriptManager
/UpdatePanel
controls.
- Another with Partial Rendering.
The example is a simple application. It allows the user to import the contents from a list of .CSV files when placed on the 'ImportFiles' folder on the application server. It also allows the user to synchronize the imported data with the database if the integrity checks on the imported data find everything is OK. These two actions are initiated by the clicks on the two buttons: 'Import' and 'Synchronize'. Import and Synchronize are two distinct steps, and in this example, we have not added the details of the .CSV parsing, integrity checks on the Imported data, and finally, the synchronization process on the database; instead, we have simulated them with delays and a simple progress animation (busy.gif) on the Page. On the Page Load
Event, looking at the file name attributes, only the last chronological file name will be picked up from the "/Importfiles" folder and then compared with the LastSync file as stored in the <appSettings>
sections in the Web.config file - if it is chronologically greater than the LastSync file name, it will appear on the list; otherwise, it will display a red colored error message saying there are no files to import. The names of the latest files in each category are saved in ViewState["AvailableFiles"]
as a DataTable
.
As a note on the requirements, the user can import the same set of files many times before synchronization is done. So, if the new set of files match with the old imported set, there should be no prompt because the user intention is clear that he or she wants to correct some errors. The application prompts the user when a last Import File Name is not matching with a last Sync File Name. The prompt is: "Last imported data not yet synchronized and will be lost. Continue?". If there are multiple files in the same category in the "/Importfiles" folder, only the latest not synched file can be imported. Once it is synchronized, it can not be re-imported. We do this in this example by disabling the button controls. Once the buttons are disabled, the only way to start the operation again is by refreshing the whole page and the whole process starts from the beginning. The following figure shows the states and their transitions with Events for the sample application:
Fig. 1a
Processing a Web Page
The following section illustrates the sequence that usually happens when the user types the URL of an ASP.NET Page from the client browser (we have not used a login page in this simplistic example, but usually, that is the start page for any application which requires authentication).
- User requests the Default.aspx Web page in the browser.
- Web Server (IIS) forwards this call to the ASP.NET runtime. The ASP.NET runtime then looks for the assembly for the page, and if it is not there, it compiles the page class from the .aspx file and its associated code-behind file. The ASP.NET runtime then executes the code, creating the HTML, which is sent to the browser. We can see the HTML code intercepting the traffic by using the Fiddler Tool. Note that the server controls are replaced by straight HTML, CSS, and JavaScript.
- The browser renders the HTML, displaying the simple form from the example, as shown in the figure below:
Fig. 2
- As shown in the page, it has got two separate sections (separated by dotted lines) - the top section contains a list of .CSV files available for Import. The bottom section describes the information about the list of files last imported and the list of files last synchronized.
- When the user clicks the 'Import' button, the browser recognizes that the 'Import' button has been clicked. The method for the form is POST, and the action is coded in Default.aspx.cs. We thus have what is called a postback to the original .aspx file. See the snapshots below from Fiddler intercepted screens. Figure 3a. shows a normal postback whereas Figure 3b, shows an AJAX asynchronous postback with partial rendering, as explained later.
Fig. 3a
Fig. 3b
- After receiving the postback request, the ASP.NET runtime on the server now performs processing for this page, which goes through various stages and is called as the Page Life Cycle as discussed earlier. An Event is raised when the user clicks the 'Import' button; this is recognized on the server and an event handler '
btnImport_Click
' in the Page
class is invoked.
- After the simulated processing delay and progress animation, the example updates the respective rows in the bottom section, i.e.,
LastImportAgencyFile
, LastImportFacilityFile
, and LastImportLocationFile
.
- The server then sends the whole response to the browser. Note that the response payload for 3b. is less than in 3a.
- The browser renders the page again for normal postback, and
PageRequestManager
does the DOM update in the case of the asynchronous postback. Now, the user sees that import is done successfully as the last import file names at the bottom are matching with the import file names at the top section along with the current import date time.
- ASP.NET preserves the state on the client side using a hidden field named
__VIEWSTATE
in the Web Form.
- When we consider the Event model in the context of the ASP.NET Web Form, an interesting thing to note is that an Event gets raised on the client due to various actions by the user (in this example, clicking the 'Import' button) and processed on the server through a Delegate and Event handler on the page class.
In a typical scenario just described above, pages are recreated with every round trip (known as postback). As soon as the server finishes processing and sends the page to the browser, it discards the page information.
This is a necessary step to preserve Web Server resources and to make web applications scalable. The next time the page is posted, the server starts all over again in creating a fresh instantiation of the Page
class and then starts processing it again. So we see that ASP.NET Web pages are stateless in nature - the values of a page's variables and controls are not preserved on the server as such, by default. However, to maintain continuity, ASP.NET works around this limitation by saving control properties between round trips. This is done in the example by saving in the View State, which is one of the many mechanisms provided by ASP.NET. We have also used hidden <input>
fields as place holders for several flags to coordinate between client side Event handlers and server side Event handlers.
Examples of the state management features of ASP.NET are:
- View State
- Control State
- Hidden Fields
- Cookies
- Query Strings
- Application State
- Session State
- Profile Properties
View State, Control State, Hidden Fields, Cookies, and Query Strings all involve storing data on the client in various ways whereas, Application State, Session State, and Profile Properties all store data in memory on the server. We will not elaborate further on this article as it is a different subject - A nice CodeProject article reference is available here: Beginners Introduction to State Management Techniques in ASP.NET.
ASP.NET also detects when a form is requested for the first time versus when the form is posted back (by checking Page.IsPostBack
), which allows us to program accordingly.
(Note: If we compare the default.apsx pages from the two sample projects, we will notice that in 'EventandAjaxExample', we had to use 'EndRequestHandler
' to hide the animation display for asynchronous postback. For 'EventExample', this is not there, and also not required as a full page refresh automatically sets the animation display to 'none
' - 'style=display: none
').
Server Side Page Events
ASP.NET allows us to set up Event handlers in server code for Events that are passed from the browser. Assume that the user is interacting with a Web Form page as in this example, which contains an 'Import' (Button) Server Control. The user clicks 'Import', and an Event is raised that is transmitted via an HTTP POST to the server where the ASP.NET page framework interprets the posted information and associates the raised Event with an appropriate Event handler, which is our customized handler implementation as per our application logic. The framework then executes this customized handler code: protected void btnImport_Click(object sender, EventArgs e)
. Using Client-Side State and the HTTP POST protocol, ASP.NET server controls give the impression as if they maintain memory on the client and react to user interaction by raising Events and handling them on the Server. For us, the developers, we need to override the virtual protected
Event handler (given in the sample) as a part of the customization to introduce our application specific code - the rest are provided by the ASP.NET Framework.
The following figure shows this mechanism conceptually.
Fig. 4
ASP.NET handles all the mechanisms of capturing, propagating, and interpreting the Events generated on the client browser. We create Event handlers in a Web Form page, and we do not need to think of this mechanism as it is happening behind the scenes and is managed entirely by the ASP.NET run time.
Note that these types of Web Form Events require a round trip or postback to the server for processing, so we should use them selectively as per our application logic and with an eye on performance.
For server controls, certain Events, typically called 'click events', cause the Web Form to be posted back to the server. Change events in server controls such as the TextBox
control, on the other hand, are captured, but do not immediately cause a POST. Instead, they are cached by the control until the next time a POST occurs. At this time, when the page is processed on the server again, all the pending Events are handled or processed.
This is usually the case but when the situation demands immediate POST. Sserver controls that support a change Event include an AutoPostBack
property. When this property is set to true
, the control's change Event causes the form to POST immediately, without waiting for a click Event. For example, by default, a DropDownList
control's OnSelectedIndexChanged
Event does not cause the page to be submitted. However, by setting the control's "AutoPostBack
" property to true
, we specify that as soon as a user selects an item from the list, the page is sent to the server for handling the Event (this way, we may display the zip codes for a city).
Event Arguments
Events in ASP.NET pass two arguments: an object (object sender
) representing the object that raised the Event, and a second object containing any Event-specific information (EventArgs e
). The second argument is usually of type System.EventArgs
, but for some controls, it is of a type specific to that control. For example, for an ImageButton
Server Control, the second argument is of type ImageClickEventArgs
, which includes information about the coordinates where the user has clicked. Similarly, for TreeView
control's on demand PopulateNode
Event handler, this second argument is of type TreeNodeEventArgs
.
ASP.NET Page Life Cycle
Earlier, we briefly introduced the ASP.NET Page Life Cycle as the different processing stages on the server, and most of them are the end result of ASP.NET Events; now, let us look at the sequence in which they occur.
Since the second example enclosed is with ASP.NET Partial rendering, I have included the figure below for the ASP.NET Page Life Cycle, which includes AJAX postback and partial rendering. For postbacks with and without partial rendering, the stage after 'PreRenderComplete
' is different, as explained below.
Fig. 5
Partial Rendering
Let us go through a little more detail to understand what happens in AJAX postback with partial rendering in ASP.NET. To make an ASP.NET page a partially rendered page, we must first add a asp:ScriptManager
to the page and then define independently updatable regions by wrapping them with an asp:UpdatePanel
control. When partial-page updates are enabled, controls can asynchronously post to the server. An asynchronous postback behaves like a regular postback in that the resulting server page executes the complete page and control life cycle. However, with an asynchronous postback, page updates are limited to regions of the page that are enclosed in asp:UpdatePanel
controls and that are marked to be updated. The server sends HTML markup for only the affected elements to the browser. In the browser, the client Sys.WebForms.PageRequestManager
class performs Document Object Model (DOM) manipulation to replace existing the HTML with the updated markup. Here's the portion from the sample:
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"
EnablePartialRendering="true" AsyncPostBackTimeout="100"/>
<script type="text/javascript" language="javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
</script>
<div class ="Container">
<asp:Panel ID="pnlImport" runat="server" Width="100%" CssClass="Page">
<div class="Container">
<asp:UpdatePanel runat="server" ID="UpdatePanelDataImportFiles"
UpdateMode="Conditional">
<ContentTemplate>
<h1 class="Header">
<asp:Label runat="server" ID="lblHeading"
Text="<%$Resources:EventResources, lblCsvDataImport %>"></asp:Label>
</h1>
<p class="Label">
<asp:Label ID="lblFiles" runat="server" Text=""></asp:Label>
</p>
<asp:GridView ID="gvFiles" runat="server" AutoGenerateColumns="False"
CssClass="Gridview" Width="100%">
<Columns>
<asp:BoundField
HeaderText="<%$Resources:EventResources, gvFileName %>"
DataField="FileName"/>
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</div>
The asp:UpdatePanel
control simply adds a surrounding <div>
tag to the original markup.
Whenever the script manager detects one or more asp:UpdatePanel
controls in the page, it emits a block of script as in the following (you can verify this with the Fiddler tool):
Sys.WebForms.PageRequestManager.getInstance()._updateControls(
['tUpdatePanelDataImportFiles','tUpdatePanelSyncInfo'], [], [], 100);
The _initialize
method is a static method on the client-side Sys.WebForms.PageRequestManager
object (see MicrosoftAjaxWebForms.js). It creates a global instance of the PageRequestManager
class and initializes it. The class acts as a singleton, and the single instance can be retrieved later through the getInstance
method, as is done in the second statement. The second statement above also registers an array of UpdatePanel
controls with the client framework. In our example, two UpdatePanel
s are there (['tUpdatePanelDataImportFiles
', 'tUpdatePanelSyncInfo
']. Each server-side UpdatePanel
control is referenced through its ID.
The key action happening here is inside the _initialize
method. As said before, after creating the singleton instance of the class, the code initializes it. At this time, among other things, a handler is registered for the submit event of the DOM form object. This means that whenever the page submits a form, the AJAX script kicks in and places the request using XMLHttpRequest
instead of letting the request go through a normal browser postback. The original set of form fields is maintained, and some extra information is appended for the convenience of the server-side script manager. So an AJAX postback uploads a bit more information than a regular ASP.NET postback.
The ViewState, as well as any other hidden fields, are carried out and uploaded to the server with the request. On the way back, an updated Viewstate is downloaded along with new hidden fields, if any, and a likely shorter markup - in the Fiddler screenshot, refer Figure 3b. above, it is highlighted as 5,791 bytes. In particular, the response includes only the markup for the updatable regions that have been modified during the postback. The list includes the UpdatePanel
control UpdatePanelSyncInfo
that triggered the postback. Although not in the sample, this will include any nested panels, any other UpdatePanel
controls in the page that have the UpdateMode
property set to "Always
", and any UpdatePanel
control that is programmatically refreshed (through server side custom coding by us).
The response of an AJAX postback is a text stream that is shown on the right hand bottom side of Figure 3b. above. Note that in Figure 3b. above, when AJAX based ScriptManager
and UpdatePanel
Controls are included in the page, we see that additional WebResouce.axd, ScriptResource.axd are loaded when you clear the browser cache and load the page the first time.
For Partial rendering using ASP.NET AJAX, we need UpdatePanel
control as well as the ScriptManager
control. If a ScriptManager
control is included on the page and the UpdatePanel
contains any controls, the controls within UpdatePanel
can be asynchronously updated through AJAX.
Looking Inside ASP.NET AJAX
To trace all Web traffic that passes through Internet Explorer®, we will use the Fiddler HTTP debugger proxy app which you can download from its site. To do this, browse to the AJAX sample as given in this article and watch what happens through Fiddler; we can see that an actual HTTP POST occurs each time we invoke a partial postback event. The HTTP POST request - Figure 3b., right hand side top portion, fifth line from the top, contains the usual HTTP headers, but it also includes one that we have never seen before:
x-microsoftajax: Delta=true
This header is the key. Once the ScriptManager
control identifies this header on the server, instead of passively injecting references into the page output, it will inspect the data sent in the form POST and render a response back to the client in a format the client script understands.
Along with writing service and script references to the initial page output, the ScriptManager
control will also initialize client-side functionality. The client-side PageRequestManager
is responsible for tracking all events generated by the controls registered with the ScriptManager
.
When a postback event is fired on the client, PageRequestManager
will identify whether it was caused by any of the controls identified for Partial rendering. If it was, PageRequestManager
will cancel the postback event and repackage it. The newly packaged data from the postback event will then be transmitted to the server using the client class Sys.Net.WebRequest
. The header x-microsoftajax: Delta=true
will be set in the POST request sent to the server through Sys.Net.WebRequest
.
On the server side, the ScriptManager
will be notified of the data in the form POST through LoadPostData
. LoadPostData
lets individual controls filter through the form POST for pertinent information. (This is a standard event not specific to ASP.NET AJAX). If we refer to the Page Life Cycle Events in Figure 5 above, we'll see that LoadPostData
occurs immediately after InitComplete
on the page. Within LoadPostData
, the ScriptManager
control identifies the controls that caused the form POST along with the UpdatePanel
the control resided in.
The ScriptManager
control now has recognized a partial postback and has identified the controls that caused the postback. The ScriptManager
control completely overwrites the default Render
method for its host page. Now we see that our new Page
class introduces its own format for rendering controls to the page output stream.
Finally, the client framework gets the asynchronous response from the server and parses out data. The ScriptManager
control has packed into the response all the control IDs and new markups so the client framework can parse scripting operations on the browser's Document Object Model (DOM) to update the page content. Given that this whole process occurred asynchronously, the browser screen is quickly and silently updated, and the user of the Web page gains a better experience without any pause in interactions or flickers.
Fig. 6
Combining Client and Server Events
We cannot specify a client-side event in the HTML syntax for a web server control, say for an Import button server control. Instead, add an event attribute to the control at run time in the server code using code such as the following:
btnImport.Attributes.Add("onclick", "confirmImport('" +
Resources.EventResources.alertImport + "');");
Conclusion
In this article, we have gone through the concepts in the ASP.NET Web Form Programming model along with Partial rendering in ASP.NET AJAX postback. Later, we have analyzed the payload which travels between the client and server during a round trip or postback. During the code walkthrough of the ASP.NET Web Form model based sample application, we tried to understand the driving force in this approach. Microsoft designers have abstracted the development model in such a way that it fits exactly like the Windows desktop model of development and helps in rapid application development (RAD). As you see, we need to understand the design intent of this Programming model to apply this in our Web application.
Lastly, a note on the limitation in the ASP.NET Web Form model with Partial rendering. For example, in this model, if there are two Partial Rendering calls occuring at the same time, the oldest one is killed to make room for the newest. If you need to look for a smarter implementation of an AJAX enabled ASP.NET Web Form model, then please see the following: Gaia Ajax: A New Approach to ASP.NET AJAX, by Dino Esposito.
Finally, note that this article does not suggest that the ASP.NET Web Form programming model is the best possible way to develop Web applications, especially when we consider testability and separation of concerns, but it is adequate in certain scenarios, and it helps in rapid program development.
References
- Hollywood Principle
- An Introduction to Delegates, by Jeffrey Richter
- Delegates Part 2, by Jeffrey Richter
- Implementation of Events with Delegates, by Jeffrey Richter
- An Extensive Examination of User controls, by Scott Mitchell
- Comparing Web Forms and ASP.NET MVC, by Dino Esposito
- Comparison of Architecture Presentation Patterns, by Shivprasad Koirala
- Practical ASP.NET: A collection of articles, by Peter Vogel & Others
- Web Presentation Patterns from Microsoft
- Model View Presenter (for making testable UI in your Web Application), by Jean-Paul Boodhoo
- Gaia Ajax: A New Approach to ASP.NET AJAX, by Dino Esposito
Acknowledgements
This particular topic is actually a result of doing hands on study with two summer students: Mr. Balu Avhad and Mr. Mayur Potulwar of Pune University. They helped me in analyzing payload data by intercepting page traffic between the client and Web Server using Fiddler.
History
- Initial cersion submitted on Apr. 13, 2010.
- Added Figure 1a. on Apr 15, 2010.