Working with Client-Side Xml Data Islands
via Server-Side ASP.NET code

by Peter A. Bromberg, Ph.D.

Peter Bromberg

"And somewhere men are laughing, and somewhere children shout, But there is no joy in Mudville — mighty Casey has struck out." -- Ernest Lawrence Thayer ,"Casey at the Bat, a Ballad of the Republic," first published SF Daily Examiner, 1888

We have had several forum posts regarding this topic recently and so I thought it might be useful to revisit it with an example. Client-side Xml Data Islands and databinding have been around with Internet Explorer for a long time - way before .NET came on the scene. They have many useful purposes, including working with Exchange data via WebDAV, and being able to use a client-side Xml Data Island as the source for an XslTransform that displays data. The major issue with ASP.NET is how to get the Xml into the page. That's where it can become troublesome for ASP.NET developers. How do I get my data on the server, the way I normally would with ASP.NET, and then bind it to an Xml DataIsland so it's available on the client?

There are a number of techniques available for doing this; the one I present here is one of the simplest and should serve as a basis for further experimentation for those who are so inclined.



The first thing we need to do is set up a Data Island and table datasrc on the HTML (aspx) portion of our page just as we did before ASP.NET came along:

<body MS_POSITIONING="GridLayout">
  <xml id="customerisland" runat="server"></xml>
  <form id="Form1" method="post" runat="server">   
   <table datasrc="#customerisland" style="FONT-FAMILY: Arial">
   <thead>
   <tr bgcolor ="lightgrey">
   <td>CustID</td>
   <td>Company</td>
   <td>Contact</td>
   <td>City</td>
   <td>Phone</td>
   </tr>
   </thead>
   <tr bgcolor="lightgreen">
     <td><div datafld="CustomerID"></div>
     </td>
     <td><div datafld="CompanyName"></div>
     </td>
     <td><div datafld="ContactName"></div>
     </td>
     <td><div datafld="City"></div>
     </td>     
     <td><div datafld="Phone"></div>
     </td>
    </tr>
   </table>
  </form>
 </body>

Note above that we have the required "xml" tag with an id of "customerisland". However, I've added the "runat=server" tag attribute, which now provides us with server-side access to our island. The rest of the code is your standard table datasrc="#customerisland" client side IE databinding attribute, along with the required "datafld" attributes for the columns we want to bind.

Now let's move to the codebehind and see how it all "hooks up":

using System;
using System.Configuration;
using System.Data;
using System.IO;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using Microsoft.ApplicationBlocks.Data;

namespace XmlIsland
{
 public class Default : Page
 {
  protected HtmlGenericControl customerisland;
  private void Page_Load(object sender, EventArgs e)
  {
   DataSet ds = GetDataSet();
   string xml = DataSetToXml(ds);
   ds.Dispose();
   //Add XML string to the client-side data island 
   customerisland.InnerHtml  = xml;
  }

  private string DataSetToXml(DataSet ds)
  {
   StringWriter writer = new StringWriter();
   ds.WriteXml(writer,XmlWriteMode.IgnoreSchema);
   return(writer.ToString());
  }

  private DataSet GetDataSet()
  {
   string cnString=(string)ConfigurationSettings.AppSettings["ConnectionString"];
   return SqlHelper.ExecuteDataset(cnString,CommandType.Text, "Select * from Customers");
  }



  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   InitializeComponent();
   base.OnInit(e);
  }
  
  private void InitializeComponent()
  {    
   this.Load += new EventHandler(this.Page_Load);
  }
  #endregion
 }
}

You can see in the code above that I've added an HtmlGenericControl to match the control declared on the page. The nice feature of the HtmlGenericControl is that it can represent an HTML server control tag not directly represented by a .NET Framework class. In other words, "whatever you want"! In the Page_Load handler I get my DataSet of Customers from Northwind exactly as we would for any other ADO.NET Data call. Then, we pass the DataSet into a DataSetToXml method that simply returns the OuterXml of the DataSet via the WriteXml method. Finally, this is bound to the InnerHtml property of our HtmlGenericControl that corresponds to the client - side "xml" tag, and we are done!

At this point, we have a legitimate Xml Data Island consisting of the results of our "Select * from Customers" Sql call, and we are free to do any DOM Scripting or other client-side databinding we want. We can also include an Xsl stylesheet in another xml tag, and perform a client-side transform if desired. The donwload includes the ApplicationBlocks.Data "SqlHelper" class.

Here is a code snippet that illustrates how one would "read the xml" back into a DataSet on a POST:

private void Button1_Click(object sender, System.EventArgs e)
{
DataSet ds = new DataSet();
byte[] b = System.Text.Encoding.ASCII.GetBytes(customerisland.InnerHtml);
MemoryStream ms = new MemoryStream(b);
ds.ReadXml(ms);
this.Label1.Text="dataset table has" +ds.Tables[0].Rows.Count.ToString() + " rows.";
}

By the way, you might be wondering what is the significance of the quote from "Casey at the Bat". None at all, other than that the World Series is over and it made me think of the last time we went to New York (home town for me) and saw Penn and Teller. In their opening act, Penn sits in a chair with a rope tied to it, going over a roof beam from which dangles Teller, tied up in a straightjacket. Penn informs the audience that he will read "Casey at the Bat" and when he finishes, he will get up. If Teller hasn't extracted himself by that time, of course he would fall to the floor on his head. If you weren't familiar with this classic poem before this, you certainly would be after that!

Download the Visual Studio.NET 2003 solution that accompanies this article

 


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.
Article Discussion: