Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

nxAjax - An AJAX Library

4.83/5 (13 votes)
12 Feb 2010MPL8 min read 1   884  
nxAjax is a .NET-based easy to use AJAX framework.

Index

Introduction

nxAjax is an easy to use ASP.NET jQuery AJAX library. Its features include:

  • jQuery JavaScript core
  • AJAX WebControl postback modes: Async or Sync
    • AjaxQueue (by Pat Nakajima) used by Sync postbacks
    • Auto "loading message" in Sync postbacks (in MainPage div -> id="loading")
    • Auto loading image in Async postbacks (each control: LoadingImg or LoadingImgId attribute)
  • MainPage with container loading ContainedPage.
  • Multilanguage system
  • Template based Web Render
  • Low bandwidth usage: Only posts the current control value
    • Only posts form content when ISubmit control is clicked
  • DOCTYPE XHTML 1.1 W3C compliant

[Index]

Beginning with nxAjax

To use nxAjax, add a reference to the "nxAjax.dll" assembly.

Image 1Image 2

For a more convenient use of controls within the Toolbox, you can right click and select "Choose Items...". In the new form, browse the "nxAjax.dll" assembly and mark all its components.

Image 3

Image 4

Now, we will have our Toolbar as follows:

Image 5

[Index]

Quick Example

Create a new Web Project in Visual Studio 2008, and add a reference to the nxAjax binary. Add this to the Web.Config file:

XML
<system.web />
...
   <pages />
      <controls />
         ...
         <add assembly="nxAjax" 
           namespace="Framework.Ajax.UI.Controls" 
           tagprefix="ajax" />
      </controls />
   </pages />
   <httphandlers />
       ....
      <add validate="false" 
         type="Framework.Ajax.HttpHandlers.ScriptResourceHandler, nxAjax" 
         path="AjaxScriptResource.axd" verb="GET,HEAD" />
      <add validate="false" 
         type="Framework.Ajax.HttpHandlers.FileUploadHandler, nxAjax" 
         path="AjaxUploadFile.axd" verb="*" />
   </httphandlers />
...
</system.web />

[Index]

Using MainPage and ContainedPage

Edit default.aspx like this:

XML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
    <title>My nxAjax Test</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <ajax:Container ID="container" 
            runat="server"></ajax:Container>
    </div>
    </form>
</body>
</html>

Edit default.aspx.cs:

C#
using System;
using System.Collections.Generic;
using Framework.Ajax.UI;
using Framework.Ajax.UI.Controls;

public partial class _Default : Framework.Ajax.UI.MainPage 
{
    protected void Page_Load(object sender, EventArgs e)
    {
         if (!IsPostBack)
            container.ContainedPage = "Contained1.aspx";
    }
}

Create a new WebForm named "Contained1.aspx":

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true" 
   CodeFile="Contained1.aspx.cs" Inherits="Contained1" %>
<form id="form1" runat="server">
<div>
    <ajax:FileUpload ID="btnFile" runat="server" 
            UploadingMessage="Uploading..." 
            ExtensionNotAllowedMessage="Only image files!" 
            Text="Upload image" 
            LoadingImg="ajax-loader.gif" 
            OnServerComplete="btnFile_ServerComplete"></ajax:FileUpload>
    <ajax:CheckBox ID="chkTest" Checked="true" 
            runat="server"></ajax:CheckBox>
    <ajax:Submit ID="btnSubmit" Value="Send" 
            runat="server" 
            OnServerClick="btnSubmit_ServerClick"></ajax:Submit>
</div>
</form>

Edit Contained1.aspx.cs:

C#
using System;
using System.Collections.Generic;
using Framework.Ajax.UI;
using Framework.Ajax.UI.Controls;

public partial class Contained1 : Framework.Ajax.UI.ContainedPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            btnFile.AllowedExtensions.Add("jpg");
            btnFile.AllowedExtensions.Add("gif");
            btnFile.AllowedExtensions.Add("png");
            btnFile.AllowedExtensions.Add("bmp");

            btnSubmit.Disabled = true;
        }
    }
    protected void btnSubmit_ServerClick(AjaxControl sender, string value)
    {
        System.Web.HttpPostedFile file = btnFile.File;
        if (!chkTest.Checked)
            return;

        if (file == null)
            DocumentAlert("not file uploaded");
        else
        {
            DocumentAlert(file.FileName + " saved!");
        }
    }
    protected void btnFile_ServerComplete(AjaxControl sender, string value)
    {
        DocumentAlert(value + "  uploaded, you can " + 
                      "click on 'send' button...");
        btnSubmit.Disabled = false;
    }
}

Launch and test it ;)

[Index]

Using ajax:Form

In the Quick Example, add a new WebForm named Default2.aspx:

XML
<system.web>
<%@ Page Language="C#"  EnableEventValidation="False" 
   AutoEventWireup="true" CodeFile="Default2.aspx.cs" 
   Inherits="Default2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
    <title>Don't use it, it does not works... :(</title>
</head>
<body>
    <ajax:Form runat="server" ID="formu">
        <div>
            <ajax:Button ID="btnOne" Value="One" 
                runat="server" 
                OnServerClick="btnOne_ServerClick"></ajax:Button>
            <ajax:Button ID="btnTwo" Value="Two" 
                runat="server" 
                OnServerClick="btnTwo_ServerClick"></ajax:Button>
            <ajax:TextBox ID="txtOne" runat="server" 
                Value="One"></ajax:TextBox>
            <ajax:Submit ID="submitOne" runat="server" 
                OnServerClick="submitOne_ServerClick"></ajax:Submit>
        </div>
    </ajax:Form>
   <form id="form1" runat="server">
        <div>
            <asp:Button ID="btnAsp" Text="Asp" 
                runat="server" OnClick="btnAsp_Click" />
            <asp:TextBox ID="txtAsp" Text="" 
                AutoPostBack="True" runat="server" 
                OnTextChanged="btnAsp_Click" />
        </div>
    </form>
</body>
</html>
</system.web>

In order for this to work properly, you should modify the WebForm properties:

C#
EnableViewState = true;
EnableEventValidation = false;
ViewStateEncryptionMode = System.Web.UI.ViewStateEncryptionMode.Never;
EnableViewStateMac = false;

And, add event code management in the code-behind. The final result should be something like:

C#
using System;
using System.Collections.Generic;
using System.Linq;

using Framework.Ajax.UI;
using Framework.Ajax.UI.Controls;

public partial class Default2 : System.Web.UI.Page
{
    public Default2() : base()
    {
        this.EnableViewState = true;
        this.EnableEventValidation = false;
        this.ViewStateEncryptionMode = 
             System.Web.UI.ViewStateEncryptionMode.Never;
        this.EnableViewStateMac = false;
    }
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            
        }
    }
    protected void btnOne_ServerClick(AjaxControl sender, string value)
    {
        btnOne.AjaxController.DocumentAlert("Hi!! " + value);
        txtOne.Value = "Three";
    }
    protected void submitOne_ServerClick(AjaxControl sender, string value)
    {
        txtOne.Value = "One";
    }
    protected void btnTwo_ServerClick(AjaxControl sender, string value)
    {
        btnOne.AjaxController.DocumentAlert("Hi!! " + value);
        txtOne.Value = "Two";
    }
    protected void btnAsp_Click(object sender, EventArgs e)
    {
        txtOne.AjaxController.DocumentAlert("Hi! " + btnAsp.Text);
        txtOne.Value = "Three";
    }
}

[Index]

How it Works

The client events store JavaScript that will be evaluated when they will be raised, always on the client side. The server events are handled by ASP.NET running on the web server and returns the amendments.

The Container control is a special control for management and operation. Its function is to be a container of ContainedPages. These are nxAjax web pages (like MainPage) displayed as a piece of code and a type of entity in a single form.

In this way, we can navigate between different web pages without having to return to reload all AJAX libraries, or re-create the Web format main container. It can resemble a UserControl, but which is loaded dynamically without being instantiated within the main container.

[Index]

MainPage

For now, MainPage is the requirement for the nxAjax library to work as it does. MainPage inherits from AjaxPage (which inherits from the .NET framework System.Web.UI.Page). And it overwrites much of its functionality. It clears all JavaScript from the Microsoft code, transforms the format of the form, adds the JavaScript library (jQuery, internals, ...) and processes requests in a way that the library can understand.

The viewstate is stored in session variables so it is no longer on the served page. MainPage removes doPostBack functions and the __VIEWSTATE hidden input. And, it also provides a new template and multilanguage systems.

[Index]

ContainedPage

A ContainedPage is only loaded into a container control (Framework.Ajax.UI.Controls.Container). And again in the MainPage. It inherits from AjaxPage (which inherits from the .NET framework System.Web.UI.Page). But unlike its older sister MainPage, it does not load any scripts. So it is dependent. ContainedPage is the tool we use to dynamically load content from AJAX on our website.

AjaxUserControl

AjaxUserControl works like System.Web.UI.UserControl. But if you want to dynamically load content, it is better to use ContainedPage.

[Index]

AjaxControl

The AjaxControl server control is the base of the entire nxAjax library. Every control inherits from this.

To render AjaxControl, we use two methods: RenderHTML and RenderJS. The first writes the HTML code that we see on the Web. And, the second renders the JavaScript used for initialization and status changes.

To avoid overload, the HTML rendering uses an internal cache for each instance of the control. And it is written only once, when the page is loaded the first time.

Then, rendering JavaScript comes into play. It is launched the first time and then on each postback which changes its status.

To force a status change or otherwise, use the functions AjaxUpdate and AjaxNotUpdate.

Every AjaxControl postback has two methods, synchronous and asynchronous. The default is Sync.

In the synchronous call context uses an AJAX queue. It adds requests to be loaded sequentially. If you want to show a loading screen during the server processing, add in MainPage a div object with id="loading".

Asynchronous calls are made for each of the controls at the time of requesting. The PostBackMode property specifies it. And, if you want to add a loading image while processing the request, you can set these properties: LoadingImg (image source) or LoadingImgID (image control ID).

AjaxControl postback only posts the current control value. If you want to post all the form content, you should use the ISubmit control (like Submit or LinkSubmit).

Finally, the AjaxPage property gets the container page: ContainedPage or MainPage.

[Index]

Why DOCTYPE XHTML 1.1?

Using the nxAjax Template System involves converting all the HTML code to XML files. So, in order to meet the standards, we have chosen the option to be W3C compliant in the XHTML 1.1 context.

[Index]

Using a Multi-Language System

Open the Quick Example project. Create a new file named "english.language". You can add all the application strings here:

#
# This is a coment, you can write what you want here...
#
# 
# English Language File
#
# Information section:
[INFO]
name=English
id=ENG
#
#Dictionary section:
[DICTIONARY]
# Format:
# [MyKey]=[Literal]
Test.ErrorMessage01=not file uploaded
Test.SavedMessage=%s saved!
Test.UploadedMessage=%s uploaded, you can click on 'send' button...

Now, go to Menu -> Website -> Add New File, and select "Global Application Class". Open the Global.asax file and add this:

C#
...
void Application_Start(object sender, EventArgs e) 
{
    // Code that runs on application startup
    Application["Language"] = 
      new Framework.Ajax.Language(Server.MapPath("english.language"));
}
...

Or this:

C#
...
void Session_Start(object sender, EventArgs e) 
{
    // Code that runs when a new session is started
    Session["Language"] = new Framework.Ajax.Language(
        Server.MapPath("english.language"));
}
...

Edit Contained1.aspx.cs:

C#
public partial class Contained1 : Framework.Ajax.UI.ContainedPage
{
    ...
    protected void btnSubmit_ServerClick(AjaxControl sender, string value)
    {
        System.Web.HttpPostedFile file = btnFile.File;
        if (!chkTest.Checked)
            return;

        if (file == null)
            DocumentAlert(lang["Test.ErrorMessage01"]);
        else
        {
            DocumentAlert(lang["Test.SavedMessage"].Replace(
                          "%s", file.FileName));
        }
    }
    protected void btnFile_ServerComplete(AjaxControl sender, string value)
    {
        DocumentAlert(lang["Test.UploadedMessage"].Replace("%s", value));
        btnSubmit.Disabled = false;
    }
}

[Index]

Template Based Render

Template in MainPage

With the Quick Example project, we are going to use nxAjax templates. Open default.aspx and delete all HTML tags:

XML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Default.aspx.cs" Inherits="_Default" %>
<form id="form1" runat="server"></form>
<ajax:Container ID="container" 
   runat="server"></ajax:Container>

ASP.NET needs a form with the attribute runat="server" in order for this to work... Create a new "main.template" empty text file:

XML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
    <title>My nxAjax Test</title>
</head>
<body>
    <div>
        <ajax:Container ID="container" runat="server"></ajax:Container>
    </div>
</body>
</html>

Replace the AJAX control ASPX code with a tag like "<$ControlID$>". And, you must add two special tags in the MainPage: <$PreScript$> and <$PostScript$>. The first in the header section, and the second at the end of the document body:

XML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
    <title>My nxAjax Test</title>
    <$PreScript$>
</head>
<body>
    <div>
        <$container$>
    </div>
    <$PostScript$>
</body>
</html>

Edit default.aspx.cs:

C#
public partial class _Default : Framework.Ajax.UI.MainPage 
{
    protected void Page_Load(object sender, EventArgs e)
    {
         this.TemplateFile = "main.template";
         if (!IsPostBack)
            container.ContainedPage = "Contained1.aspx";
    }
}

Inside the MainPage template, you can use two optional special tags: <$InitForm$> and <$EndForm$>, in order to submit the main form.

XML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
    <title>My nxAjax Test</title>
    <$PreScript$>
</head>
<body>
    <$InitForm$>
    <div>
        <$container$>
    </div>
    <$EndForm$>
    <$PostScript$>
</body>
</html>

[Index]

Template in ContainedPage

Open "Contained1.aspx" and delete all HTML tags (except the server form):

XML
<%@ Page Language="C#" AutoEventWireup="true" 
   CodeFile="Contained1.aspx.cs" Inherits="Contained1" %>
<form id="form1" runat="server"></form>
<ajax:FileUpload ID="btnFile" runat="server" 
            UploadingMessage="Uploading..." 
            ExtensionNotAllowedMessage="Only image files!" 
            Text="Upload image" 
            LoadingImg="ajax-loader.gif" 
            OnServerComplete="btnFile_ServerComplete"></ajax:FileUpload>
<ajax:CheckBox ID="chkTest" Checked="true" runat="server"></ajax:CheckBox>
<ajax:Submit ID="btnSubmit" Value="Send" runat="server" 
            OnServerClick="btnSubmit_ServerClick"></ajax:Submit>

Create a new "container1.template" empty text file, with <$ControlID$> tags where you want to show each control:

XML
<div>
    <$btnFile$>
    <$chkTest$>
    <$btnSubmit$>
</div>

You can optionally add a <$PostBack$> tag if you want to put the postback controls in a specified position in the document.

Add this line to Contained1.aspx.cs:

C#
...
public partial class Contained1 : Framework.Ajax.UI.ContainedPage
{
    protected void Page_Load(object sender, EventArgs e)
    {
        this.TemplateFile = "container1.template";
        if (!IsPostBack)
        {
...

Inside the ContainedPage template, you do not need to declare an HTML form. This is because of ContainedPage is a form, and the render will write the begin and end form tags.

[Index]

Template with XML Source

You have the option to create your own XML ASP structures. This is not compatible with the previous method. Open "container1.template" file and modify it to something like:

XML
<div>
    <$File$>
    <$Submit$>
</div>

To fill this template, we need to modify "Contained1.aspx":

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Contained1.aspx.cs" Inherits="Contained1" %>
<form id="form1" runat="server"></form>
<file>
     <ajax:FileUpload ID="btnFile" runat="server" 
            UploadingMessage="Uploading..." 
            ExtensionNotAllowedMessage="Only image files!" 
            Text="Upload image" 
            LoadingImg="ajax-loader.gif" 
            OnServerComplete="btnFile_ServerComplete"></ajax:FileUpload>
</file>
<submit>
     <ajax:CheckBox ID="chkTest" Checked="true" 
        runat="server"></ajax:CheckBox>
     <ajax:Submit ID="btnSubmit" Value="Send" 
        runat="server" 
        OnServerClick="btnSubmit_ServerClick"></ajax:Submit>
</submit>

Note you can nest two or more AJAX controls inside an XML element. If you run the project, the result will look like in the previous example. When the template system processes an ASPX document, it checks the document, beginning with a ".

XML
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Contained1.aspx.cs" Inherits="Contained1" %>
<?xml version="1.0" encoding="utf-8"?>
<page>
     <form id="form1" runat="server"></form>
     <file>
          <ajax:FileUpload ID="btnFile" runat="server" 
                 UploadingMessage="Uploading..." 
                 ExtensionNotAllowedMessage="Only image files!" 
                 Text="Upload image" 
                 LoadingImg="ajax-loader.gif" 
                 OnServerComplete="btnFile_ServerComplete"></ajax:FileUpload>
     </file>
     <submit>
          <ajax:CheckBox ID="chkTest" Checked="true" 
              runat="server"></ajax:CheckBox>
          <ajax:Submit ID="btnSubmit" Value="Send" 
             runat="server" 
             OnServerClick="btnSubmit_ServerClick"></ajax:Submit>
     </submit>
</page>

And it works too.

[Index]

Template Areas

Going into modeling templates, we found a series of special commands to create template parts. These template parts are named "areas". When defining an area, you must use two special tags: <!$Begin AreaName> and <!$End AreaName>.

XML
<!$Begin divArea>
  <div>
    <$object$>
  </div>
<!$End divArea>
<$divs$>

Or:

XML
<!$Begin divArea>
  <div>
    <$file$>
    <$submit$>
  </div>
<!$End divArea>
<$divs$>

Inside the ASPX XML code, you must define an area tag with the attributes:

  • Id: Area name.
  • Place: Template tag where the area will be rendered.
  • Method: Add or Allocate. Optional. By default, Add.
    • Add for more than one area in the same position.
    • Allocate for only one area in this position.

To fill this new template, we need to modify "Contained1.aspx":

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Contained1.aspx.cs" Inherits="Contained1" %>
<form id="form1" runat="server"></form>
<area id="divArea" place="divs" method="allocate">
     <object>
          <ajax:FileUpload ID="btnFile" runat="server" 
                 UploadingMessage="Uploading..." 
                 ExtensionNotAllowedMessage="Only image files!" 
                 Text="Upload image" 
                 LoadingImg="ajax-loader.gif" 
                 OnServerComplete="btnFile_ServerComplete"></ajax:FileUpload>
          <ajax:CheckBox ID="chkTest" Checked="true" 
             runat="server"></ajax:CheckBox>
          <ajax:Submit ID="btnSubmit" Value="Send" 
             runat="server" 
             OnServerClick="btnSubmit_ServerClick"></ajax:Submit>
     </object>
</area>

And also:

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Contained1.aspx.cs" Inherits="Contained1" %>
<form id="form1" runat="server"></form>
<area id="divArea" place="divs">
     <file>
          <ajax:FileUpload ID="btnFile" runat="server" 
                 UploadingMessage="Uploading..." 
                 ExtensionNotAllowedMessage="Only image files!" 
                 Text="Upload image" 
                 LoadingImg="ajax-loader.gif" 
                 OnServerComplete="btnFile_ServerComplete"></ajax:FileUpload>
     </file>
     <submit>
          <ajax:CheckBox ID="chkTest" Checked="true" 
            runat="server"></ajax:CheckBox>
          <ajax:Submit ID="btnSubmit" Value="Send" 
            runat="server" 
            OnServerClick="btnSubmit_ServerClick"></ajax:Submit>
     </submit>
</area>

And, if we want to create two div blocks instead of one (with the first example):

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true" 
    CodeFile="Contained1.aspx.cs" Inherits="Contained1" %>
<form id="form1" runat="server"></form>
<area id="divArea" place="divs">
     <object>
          <ajax:FileUpload ID="btnFile" runat="server" 
                 UploadingMessage="Uploading..." 
                 ExtensionNotAllowedMessage="Only image files!" 
                 Text="Upload image" 
                 LoadingImg="ajax-loader.gif" 
                 OnServerComplete="btnFile_ServerComplete"></ajax:FileUpload>
     </object>
</area>
<area id="divArea" place="divs">
     <object>
          <ajax:CheckBox ID="chkTest" Checked="true" 
             runat="server"></ajax:CheckBox>
          <ajax:Submit ID="btnSubmit" Value="Send" 
             runat="server" 
             OnServerClick="btnSubmit_ServerClick"></ajax:Submit>
     </object>
</area>

[Index]

Template Includes

Another special command is "<!$Include TemplatePartFileName>". It will be replaced by the template file referenced. The template file name is the relative path from the current document to the document we want to include.

Create a new empty text file named "divpart.template":

XML
<!$Begin divArea>
  <div>
    <$object$>
  </div>
<!$End divArea>

And, modify the "container1.template" file:

XML
<!$Include divpart.template>
<$divs$>

And it works like the others.

[Index]

Template with Language

The template based render system can auto-replace strings using the language file. You have to write another special tag with the language key: <&LanguageKey&>

If you have to create a language file, you can try to add the page title to "english.language":

...
[DICTIONARY]
...
Title=My nxAjax Test

And replace in the "main.template" file, the page title by the language tag:

XML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
--- <title><&Title&></title>
    <$PreScript$>
</head>
<body>
    <div>
        <$container$>
    </div>
    <$PostScript$>
</body>
</html>

[Index]

Template in GridView

The nxAjax GridView control contains the attribute ContentTemplateFileName. It allows to set a template file name, and the grid will render based on this template file.

XML
<ajax:GridView ID="gridImages" runat="server" 
               ContentTemplateFileName="grid.template">
  <ajax:GridImageColumn DataColumn="img" />
  <ajax:GridLabelColumn DataColumn="name" />
</ajax:GridView>

The template file has to have three areas: "header", "content", "footer".

  • header: The first (no repeat) code you want to render.
  • content: Repetitive code; for each row, it will render a content area by replacing each <$Column{N}$>.
  • footer: The last (no repeat) code you want to render.
XML
<!$Begin header>
<div class="imageListDiv">
<!$End header>

<!$Begin content>
   <div class="imageDiv">
      <$Column{0}$><br />
      <span><$Column{1}$></span>
   </div>
<!$End content>

<!$Begin footer>
</div>
<!$End footer>

[Index]

More Information

You can read more about this here: nxAjax CodePlex page.

License

This article, along with any associated source code and files, is licensed under The Mozilla Public License 1.1 (MPL 1.1)