OutPost: Post Back Over XmlHttp

Wednesday, October 05, 2005

Perform real Post Backs of ASP.NET Web Forms without reloading the entire page.
Keywords: AJAX, XmlHttp, WebForms, Post Back, DHTML, Web Service, OutPost.

A screenshot of The iGoogle Demo
Screenshot of "The iGoogle Demo" in the demo project

Introduction

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.

AJAX is a maintenance nightmare

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.

Example

Lets 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 Post Back 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.

What makes OutPost unique?

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.

Unique advantages of OutPost

  • A single .js include file is enough for OutPost.
  • OutPost converts any ASP.NET WebForm into an AJAXed WebForm without any modifications to the code.
  • It has cross-browser support built-in.
  • The Post Backs are 100% real and server-side events are triggered, as you'd expect them to trigger.
  • Multiple server-side WebForms (.aspx-pages) are supported side by side on the same page.
  • Excess traffic between client and server is eliminated (the view-state stays on the server and only modified HTML is sent back to the client).
  • A lightweight javascript client-framework makes it possible to add, remove and Post Back WebForms by script.

Other OutPost features

  • Output caching is supported on WebForm-level.
  • Unicode characters are supported.
  • A WebForm has its own Session.
  • No custom controls are needed.
  • Main pages and WebForms can be designed in VS.NET.

OutPost-enabling a single WebForm

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:

Background

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:

ASP.NET WebForms

+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 client and server.
+CROSS-BROWSER: The HTML and javascript it produces automatically match the capabilities of the target browser.
+CACHED OUPUT: 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 cpu's this makes the page flicker.

AJAX

+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.

OutPost - The best of both worlds

In OutPost the advantages of ASP.NET WebForms and AJAX are combined. OutPost takes care of the following:

  1. Need for cross-browser DHTML is eliminated.
  2. A real Post Back is executed and server-side events are fired.
  3. Excess traffic is eliminated.
  4. Page reloads are eliminated.

That easy, right? Yes, let's take it step by step.

Step by step

The steps below describe the life of a Post Back when using OutPost:

  1. Need for cross-browser DHTML is eliminated

    • A main page loads the Web Form Page and in that process (on the server) the HTML and ViewState are stored for later use (it is used again on the server when posting back the WebForm). Also the needed link(s) to javascript file(s) are inserted in the 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 contents of the main page. The main page does not necessarily need to have its own web form.

    • The above is optional and you can insert the javascript link in your code yourself and use the 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 Post Back.

  2. A real Post Back is executed and server-side events are fired

    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 Post Back using HttpWebRequest and HttpWebResponse. Headers containing user agent, language and session cookie are sent on to the WebForm Page.

  3. Excess traffic is eliminated

    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 post back is compared to the HTML tree structure of the last post back. 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 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.

  4. Page reloads are eliminated

    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.

Using the code

A single WebForm

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>

Using a main page to load the WebForm

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" />

Having two forms on the same page that depend on each other

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>

Using the Client Framework

The following example shows how you can dynamically add, remove and Post Back different forms on a page (See "The iGoogle Demo" in the demo project and the screen shot 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);

The Future of OutPost

  • Making it possible to send back changes on a smaller scale (like only setting the value of an input or only changing one option in a dropdown list).
  • I would like to incorporate simple AJAX behaviour, so that you can interact with business logic on the web server.
  • Solving the Bookmark issue. It is not possible to bookmark a WebForm page and I'm trying to find a solution to that.
  • Solving the Back-button issue. It is not possible to use Back-Button and I'm trying to find a solution to that also.

History

  • Sep 2005 - OutPost version 1.0 - Added cross-browser support, lightweight client-framework,
  • May 2005 - OutPost version 0.5 - Single web form supported, IE only.
  • Nov 2004 - First initial testing performed.

5 Comments:

Blogger Troels Wittrup said...

The article has been published at The Code Project, so go there and have a look!

- And please, share your experiences and give feedback on using OutPost!

12:02 AM  
Anonymous Anonymous said...

Sir,
Can we use Outpost in ASP 3.0 and ASP.NET 1.1.

and from where we can find those js files. is it free of cost ?

mail me to shiras.abdulrahman@gmail.com

12:36 AM  
Anonymous gener said...

Good review, thanks.
twitter - my twitter profile

2:32 AM  
Anonymous Anonymous said...

Hi! This template is simply super.... it's a pretty blog web application

9:23 PM  
Blogger michaelvk said...

This comment has been removed by the author.

3:44 AM  

Post a Comment

<< Home