Putting It All Together

The DataListView control is an effective tool for displaying a snapshot of data cached on the client. An ASP.NET page that makes use of the DataListView control differs in some respects from any other ordinary data-bound ASP.NET page. First and foremost, using the DataListView control or similar controls in a Web application requires a rich client such as Internet Explorer and requires that the .NET Framework is installed on the client. As you might expect, these requirements make such a Web application more suitable for controlled environments like an intranet than for the Internet.

On the other hand, caching data on the client allows you page through data, as well as sort and filter rows, without repeated access to the database and without tying up Web server memory with server-side cached objects. Writing a browser-managed control also lets you exploit the power of the .NET Framework on the client, although with some limitations. The DataListView control will run as partially trusted code, and although the control can administratively receive more privileges and permissions, the core code you write should not presume itself to be more than a partially trusted application. In particular, this means that file I/O should be avoided to the extent that it is possible and replaced with isolated storage whenever data persistence becomes a strong necessity.

Note

The GetSalesReportBarChart method of the Web service built in Chapter 13 creates the JPEG image that represents the chart as an in-memory image just to avoid security restrictions for file I/O. For the most part, the location of the assembly determines the restrictions it will be subject to. Locations are articulated in zones, including MyComputer, Intranet, and Internet.


Registry, clipboard, and network access are restricted also. Network access is restricted to the URL from which the control’s assembly was downloaded. Printing is allowed only through the Windows Forms common dialog box, and no direct access to the resource is permitted. Finally, both run-time and XML serialization are considered restricted functionalities whose full access is reserved for fully trusted applications.

With these considerations in mind, let’s finalize the DataListView control and build an ASP.NET page that makes use of it. A sneak preview of the final page is shown in Figure 14-3.

Figure 14-3. An ASP.NET page that creates and consumes an XML data island.


Serializing DataSet Objects to Data Islands

The sample page shown in Figure 14-3 is named dataisland.aspx and is available in this book’s sample files, along with the source code for the DataListView control. The following code shows the body of the page. Key parts of the code are shown in boldface—in particular, the data island definition and the managed control declaration.

<html>
<body>
<h1>Consuming Data Islands</h1>

<!-- Client-side XML data island -->
<xml id="xmldoc">
  <asp:xml runat="server" documentsource="employees.xml" />
</xml>
<!-- End of the data island -->

<form runat="server">
  <input type="button" value="Display Data Island Content"
    onclick="getDataFromXmlTag()">

  <object id="grid"
    classid="http:DataListView_CS.dll#XmlNet.CS.DataListView"
      height="300" width="100%">
  </object>
</form>

</body>
</html>

The data island is created using the <asp:xml> server control, which reads a previously created XML file. The employees.xml file is simply the XML normal form of a DataSet object. The DataSet object is serialized to the data island, and the page is sent to the browser. On the client, some Javascript code takes care of extracting the data island contents as XML text and passing it on to a method—Load—on the managed control. Internally, the Load method rebuilds the DataSet object and uses it to populate its own user interface. Figure 14-4 shows the ASP.NET page in action, with a filter applied and with the data sorted in ascending order by last name.

Figure 14-4. Sorting and filtering data on the client.


Note

When embedding script code in Web pages to be consumed over the Internet, you should use the Javascript language to reach the widest possible range of browsers. VBScript is limited to Internet Explorer. In this example, however, we’re making serious assumptions about the capabilities of the client—.NET Framework installed, support for the extended syntax of the <object> tag, and ability to host managed code. This means that your browser must be Internet Explorer 5.5 or, more likely, Internet Explorer 6.0 or later. So in this case you can reasonably drop Javascript in favor of VBScript.


From MSXML Documents to .NET XML Documents

When Internet Explorer detects the <xml> tag in a client page, it automatically extracts the page’s contents, creates an internal instance of the MSXML parser, and makes the data available through an XMLDOMDocument object. Note that XMLDOMDocument is not a managed object created from any of the .NET Framework classes but rather an instance of a COM object that constitutes the XML DOM representation of the data island contents. The following pseudocode, written in JScript, illustrates this point; the variable xmldoc is an XMLDOMDocument object.

// Extract the data island contents
// xmldoc is the ID of the <xml> tag
var xmldata = document.all("xmldoc").innerHTML;

// Instantiate MSXML
var parser = new ActiveXObject("Microsoft.XMLDOM");

// Parse the contents of the data island and makes
// it available as a XML DOM object. The object is given
// the same name as the <xml> tag’s ID
var xmldoc = parser.loadXML(xmldata);

If your final goal is consuming the data island within the body of a managed control, there is no need to pass through a COM-based intermediate representation of the XML data. In this case, in fact, the parser that will actually process the data is the .NET Framework XML reader. The reader needs only a string of XML data, not a COM object. On the other hand, whenever you use the <xml> tag, Internet Explorer automatically creates the XMLDOMDocument object. So if the final destination of the data island is a Windows Forms control, you might want to speed things a little bit by not using the <xml> tag, which will produce a useless COM XML DOM object. Using a hidden field offers the same functionality at a lower price. But keep in mind that this option is valid only if you plan to consume the data island contents through embedded managed code.

The Role of Script Code

To establish a connection between the host environment and the managed control, you must use script code—Javascript in particular. For this reason, while you’re designing the interface of the managed control, don’t forget what the actual callers of those methods will be. A Javascript client has different capabilities than a .NET Framework client, so you should keep the signature of public methods as simple as possible and avoid using arrays and other complex and user-defined types.

In the dataisland.aspx sample code, the connection between the data island and the managed control is made through the Load method. The Load method accepts a simple string, which results in a signature that the Javascript code can easily match, as shown here:

// At this point, Internet Explorer has already created
// the XMLDOMDocument. You can retrieve the content of the
// data island either through the XMLDocument object or
// the innerHTML property.
var data = xmldoc.XMLDocument.xml;

// Pass the data island content to the managed control
var listView = document.all("grid");
listView.Load(data);

Avoiding Problems with Submit Buttons

While developing the sample ASP.NET page to test the DataListView object, I ran into an interesting snag. I originally used the <asp:button> tag to insert a button to load the data island into the control. As a result, the data island was correctly read and the control filled, but a moment later the page refreshed, and the control lost its state and was displayed as empty. What happened? The reason for this strange behavior is that the <asp:button> tag always generates a submit button, as shown here:

<input type="submit" name="button1" value="Click me" />

As a result, the page first executes the client-side script associated with the HTML button and fills the control with the XML data. Next the browser posts the page back to the server as the submit button type mandates. This behavior is undesired for a couple of reasons. First, it produces an unneeded round-trip to the Web server. Second, the round-trip cancels the changes to the user interface that have been made on the client and that constitute the core of our efforts and our main reason for building and using a managed control. On the other hand, the Windows Forms control is not a server-side control and does not have access to the ViewState property to control its state when the page posts back.

This problem has a simple workaround: don’t use the <asp:button> tag to insert a button that is expected to interact with the managed control through client-side script code. Instead, use the <input> tag and explicitly set the type attribute to button, as shown in the following code:

<input type="button" value="Display Data Island Content"
  onclick="getDataFromXmlTag()">

Also, don’t set the runat attribute; if you do, the onclick attribute will be mistaken for server-side code to be executed. In this way, the browser executes the associated client-side script code and refreshes the page accordingly, but no postback occurs.

Using Hidden Fields and SQL Queries

Despite the fact that the <xml> tag is the official way of defining XML data islands with Internet Explorer, a hidden field is probably a better solution. With a hidden field, Internet Explorer doesn’t preprocess the XML data into a COM-based XML DOM object. This feature is welcome if you are going to process the XML data using script code. No parsing is needed if you only plan to pass the XML data island to a managed control, however. Using a hidden field or a hidden tag is a valid approach to inserting XML data in the body of an HTML page.

The following code illustrates how to create a hidden field that contains dynamically generated XML data. The data is the output you get from the XML normal form of a DataSet object. In this sample code, the DataSet object is obtained by running a query against the Customers table in the Northwind database.

<script runat="server">
private void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        string xmldata = GetDataAsXml();
        RegisterHiddenField("xml", xmldata);
    }
}

private string GetDataAsXml()
{
    SqlDataAdapter adapter = new SqlDataAdapter(
        "SELECT customerid, companyname, contactname, 
          contacttitle, city, country FROM customers",
        "SERVER=localhost;DATABASE=northwind;UID=sa;");
    DataSet ds = new DataSet();
    adapter.Fill(ds);
    return ds.GetXml();
}
</script>

Figure 14-5 shows the sample page in action.

Figure 14-5. The sample page now shows filtered data from the Customers table. The XML data has been carried using a hidden field.


Note

Another key technique you can use to refresh the page using client-side data leverages DHTML. Although this approach can be effective and powerful, it doesn’t combine well with managed code. DHTML refers to the page object model and is designed for scripting. The page object model is exposed as a suite of COM objects, and driving it from within managed code is certainly possible but not particularly easy.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.107.181