![]() |
Web Development »
Ajax and Atlas »
General
Intermediate
License: The Code Project Open License (CPOL)
OutPost: PostBack Over XmlHttpBy Troels Wittrup JensenReal postback of ASP.NET WebForms without reloading the entire page. |
C#, Javascript, XML, HTML, Windows, .NET 1.1, ASP.NET, WebForms, Ajax, VS.NET2003, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||

Screenshot of "The iGoogle Demo" in the demo project
This article assumes that you are familiar with ASP.NET WebForms. You might also want to know the basics about AJAX. This is a quote from Wikipedia on AJAX:
AJAX applications look almost as if they reside on the user's machine, rather than across the Internet on a server. The reason: pages get updated, not entirely refreshed.
�Every user action that normally would generate an HTTP request takes the form of a JavaScript call to the AJAX engine instead�, wrote Jesse James Garrett, in the essay that first defined the term. �Any response to a user action that doesn�t require a trip back to the server � such as simple data validation, editing data in memory, and even some navigation � the engine handles on its own. If the engine needs something from the server in order to respond � if it�s submitting data for processing, loading additional interface code, or retrieving new data � the engine makes those requests asynchronously, usually using XML, without stalling a user�s interaction with the application.�
Traditional web applications essentially submit forms, completed by a user, to a web server. The web server responds back by sending a new web page. Because the server must submit a new page each time, applications run more slowly and awkwardly than their native counterparts.
AJAX applications, on the other hand, can send requests to the web server to retrieve only the data that is needed, usually using SOAP or some other XML-based web services dialect. On the client, JavaScript processes the web server response. The result is a more responsive interface, since the amount of data interchanged between the web browser and web server is vastly reduced. Web server processing time is also saved, since much of it is done on the client.
Today you have to create web applications that work in both IE and Firefox, and that is definitely doable but also pretty time consuming and a maintenance nightmare.
AJAX has become very popular, because it answers a need for speed and responsiveness in web applications and there has also been the "Google" effect:
"We create interactive web applications like Google does and they use AJAX too"
Yeah, but it is not so cool, if you use 95% of the time on testing in different browsers.
AJAX falls short on two major points: It has no support of the state management in ASP.NET Web Forms and it has no support for cross-browser web applications. The goal of this article is to solve these two issues.
Let's say you have a tree-structure displayed to the user (like in Windows Explorer) and you only want to retrieve and display the sub-folders when the user expands a folder in the tree.
With AJAX you would call a web service to retrieve an array containing the subfolder names, links and icons and create the tree nodes using DHTML. You would have to create the web service methods, write cross-browser JavaScript to make it work and have hidden fields in your ASP.NET WebForm containing the state of the control.
What OutPost does is to perform a real postback through a Web Service that also manages the view-state (and keeps it on the web server). The InnerHtml of the modified elements are sent back to the client and displayed in the browser. In that way the whole process is generalized and you don't need to create Web Service methods, DHTML JavaScripts or add hidden fields for your ASP.NET controls.
So obviously you get considerable productivity gains by using OutPost to AJAX-enable your web applications.
OutPost is a new angle on AJAX. Other AJAX frameworks use specifically tailored Web Services that you have to write yourself to return the data you need. And none of the frameworks fully support the benefits of the ASP.NET Framework. With AJAX you have to re-think and re-write your code.
The decision to add "AJAX" to your pages is not a question of "do we have the time and skill to implement it". Instead it becomes a design question.
To add OutPost and AJAX-enable a WebForm, all you need is to write the following in the beginning of your .aspx file:
<script src="/OutPost/OutPost.js.aspx" type="text/javascript"></script>
But let us just zoom out for a second:
When developing interactive applications for the web, you have different models to use, and two of them are shown below. They can be combined in many ways, but if they are not combined the following is a non-pre-emptive comparison of their advantages and disadvantages:
| + | Fast and safe: Compiled code, type safe code model. |
| + | Open OOP model: Object oriented programming model, open extendable classes, reusable code. |
| + | Framework: Has an extensible framework with a fair amount of rapid development tools and web controls ready to use. |
| + | State managed: It manages the state for you using viewstate post backs. |
| + | Server-Events: An event model takes care of the communication between the client and the server. |
| + | Cross-Browser: The HTML and JavaScript it produces automatically match the capabilities of the target browser. |
| + | Cached output: Pages, controls and datasets can be cached in a variety of ways. |
| + | Fast startup: Only the HTML needed for displaying the current page is transmitted to the client. |
| - | Heavy traffic: When posting back, the whole web form including the viewstate is uploaded to the server and the whole page is then sent back to the client. |
| - | Reloads: When posting back, the whole page is refreshed, and especially on slow connections and or slow CPUs, this makes the page flicker. |
| + | Light traffic: State is not transmitted back to the server, only the needed data is transmitted |
| + | No reloads: The page is updated by using DHTML (manipulating the DOM with JavaScript). |
| - | No Server-Events: Communication with the server is done by directly calling different web service methods. |
| - | Slow and unsafe: JScript is not a compiled language and testing is pretty difficult on some devices. |
| - | Slow startup: Huge amounts of JavaScript is usually needed for client controls and these files are sent to the client on startup. |
| - | Not cross browser: Making sure the DHTML is cross browser is completely in the hands of the developer. |
| - | No framework: You have to put together your own client-control framework to manipulate the DOM. |
In OutPost the advantages of ASP.NET WebForms and AJAX are combined. OutPost takes care of the following:
That's easy, right? Yes, let's take it step by step.
The steps below describe the life of a postback when using OutPost:
HEAD section of the HTML (extra cross-browser compatibility layer scripts are added if necessary).
When loading a WebForm, you can decide whether you want all the HTML or only the outerHTML of the form. If you want several forms loaded onto the same main page, you would only need the outerHTML of each form and add that, where you'd like on the page (as long as it is not inside the page's own web form).
If you load a single WebForm you could go for the HTML of the whole page and simply let that be the content of the main page. The main page does not necessarily need to have its own web form.
<outpost:script> server-controls to add the cross-browser compatibility layers if needed.
The compatibility layers are added by the files AtlasCompat.js and AtlasCompat2.js from Atlas (the Microsoft ASP.NET 2.0 AJAX platform) and they ensure that the OutPost runtime works the same in all browsers. For example, on the window and the document elements, the attachEvent and detachEvent functions are added, so the DHTML in the OutPost runtime can be the same.
If you don't use a main page, the HTML structure and the ViewState of the first call will not be stored on the server and the first post back will have to send the ViewState to the server and the inner HTML of the whole web form will also be sent back to the client on the first postback.
The postback of the form is replaced by out-of-band calls to a .NET Web Service. The calls are made from JavaScript without reloading the page. This is done by posting a SOAP-envelope to the Web Service using XmlHttp. The SOAP-envelope contains the URI of the WebForm page (the action attribute of the form element) and the contents of the input fields in the WebForm (but not the ViewState).
The Web Service then executes the real postback using HttpWebRequest and HttpWebResponse. Headers containing user agent, language and session cookie are sent on to the WebForm page.
The HTML read from the HttpWebResponse is parsed and the tags/elements that have an ID gets picked out and put into a tree structure. This step only works if the HTML structure is correct. If the structure is not correct the inner HTML of the whole web form is sent back to the client (not the ViewState though).
The HTML tree structure of the new postback is compared to the HTML tree structure of the last postback. This is done in a bottom-up way, so first the contents of the form without any inner HTML of sub nodes are compared. If no differences are found, the inner HTML of the next sub nodes (with the same ID and ID-index) from each tree are compared without the inner HTML of their sub nodes. And so forth.
The inner HTML of the elements found to be different in the previous step are returned to the client. The DOM is updated, element by element, using cross browser DHTML.
It might seem as a bit of a crude way to just send the modified innerHTML fragments back to the client, but it really makes sense when developing cross-browser web applications.
To add OutPost and AJAX-enable a WebForm, all you need is to write the following in the beginning of your .aspx file:
<script src="/OutPost/OutPost.js.aspx" type="text/javascript"></script>
To load a page from a main page and OutPost-enable it, you write the following in your Page_Load method:
private void Page_Load(object sender, System.EventArgs e) {
Page.Controls.Add(OutPost.Core.OutPost.GetLiteralControl(
ResolveUrl("Validator7.aspx")));
}
This (when placed in the top) adds cross-browser scripts on demand, based on the client User-Agent:
<%@ Register TagPrefix="outpost"
Namespace="OutPost.Controls" Assembly="OutPost" %>
<outpost:script Runat="server" Path="~/ScriptLibrary/AtlasCompat.js"
Browsers="Netscape,Mozilla,Firefox,Apple,Safari,Mac" />
<outpost:script Runat="server" Path="~/ScriptLibrary/AtlasCompat2.js"
Browsers="Apple,Safari,Mac" />
Using JavaScript, it is possible to let two forms depend on each other:
<script type="text/javascript">
//OutPost7.aspx
function document_onkeyup() {
if (event.srcElement==Forms[0].TextBox1) {
Forms[1].TextBox1.value = event.srcElement.value;
}
}
function document_onclick() {
if (event.srcElement==Forms[0].Button1) {
Forms[1].Button1.bClicked = true;
Forms[1].doPostBack('','');
}
}
document.attachEvent("onclick",document_onclick);
document.attachEvent("onkeyup",document_onkeyup);
</script>
The following example shows how you can dynamically add, remove and postback different forms on a page (see "The iGoogle Demo" in the demo project and the screenshot from the demo in the beginning of this article):
//RssFeed.js - "The iGoogle Demo"
function DeleteBox() {
var oNodeForm = null;
if (oEventNode) {
oNodeForm = misc_getForm(oEventNode);
oEventNode = null;
}
if (oNodeForm!=null) {
oNodeForm.parentNode.parentNode.removeChild(oNodeForm.parentNode);
Forms[oNodeForm.iIndex] = null;
}
var sAction = unescape(oNodeForm.action);
FormMain.bAddBox = false;
FormMain.doPostBack("oButtonDelete",sAction);
}
function AddBox() {
var sUri = "/OutPost/Demo/RssFeed.aspx?rss="+
escape(document.getElementById('FormMain').oTextBoxAddRssUri.value);
for (var i in Forms) {
if ((Forms[i]!=null) && (unescape(Forms[i].action)==unescape(sUri))) {
alert("The feed has already been added");
return;
}
}
var oNodePanel = document.createElement("DIV");
oNodePanel.className = "cPage";
var oNodeColumn = document.getElementById("oTableCell2");
if (document.getElementById("oTableCell1").childNodes.length
<oNodeColumn.childNodes.length) {
oNodeColumn = document.getElementById("oTableCell1");
}
if (document.getElementById("oTableCell3").childNodes.length
<oNodeColumn.childNodes.length) {
oNodeColumn = document.getElementById("oTableCell3");
}
oNodeColumn.appendChild(oNodePanel);
var oNodeForm = createForm("Form1", sUri, AddBox_onerror);
oNodePanel.appendChild(oNodeForm);
document.getElementById('FormMain').oTextBoxAddRssUri.value = "";
}
function AddBox_onerror() {
alert("Error adding RSS feed");
}
function FormMain_onsuccess() {
this.base_onsuccess();
if (this.bAddBox!=false) {
AddBox();
}
this.bAddBox = true;
}
function window_onload() {
FormMain.onsuccess = FormMain_onsuccess;
}
window.attachEvent("onload", window_onload);
DIVs
oForm_doReset after each post back because of the change to the dropdowns
OutPost.Core to OutPost
ContentTypeForNoCompression MinimumSizeForCompression and ContentTypeForNoCompression constants PartsNeeded for GET request
WebForm_AutoFocus
LocalHost to specify alternative localhost domain
StringBuilder
PartsNeeded is only initialized as a StringArray if the "PartsNeeded" header is set
window_onload function: Script error if no forms present on page
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 4 Oct 2006 Editor: Smitha Vijayan |
Copyright 2005 by Troels Wittrup Jensen Everything else Copyright © CodeProject, 1999-2009 Web11 | Advertise on the Code Project |