下面创建一个基本的Web页面。当你开始时,VS已经创建了一个默认的Default.aspx供你使用。打开并加入List 11的代码。
Listing 11: Default.aspx
| <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>DB2 AJAX Sample</title> </head> <body> <form id="form1" runat="server"> <div id="heroList"> </div> <div id="notes">Choose a Hero</div> </form> </body> </html> |
第二个<div>标记, “notes”将会自动的在你写下一段的时候引入。它将会存放从Web服务中获取的XML。为了选择特定的行,你需要选择表中的一个ID。最简单的方法是使用Repeater Web对象。
- 切换到设计视图,拖曳Repeater控件到“heroList”<div>标记中。你可以在Toolbox里的Data块的标记中找到它。
- 从Repeater标记中选择一个数据源,你可以从下拉菜单中选择,如图15.

- 选择“Database”作为你的数据源类型。
- 当选择数据连接时,你可能只有一个选项,选择它,如图16.

- 这是你第一次访问这个数据连接,你可以得到一个保存连接到配置文件的提示,你可以选择接受。图17。接受给出的缺省名称“AJAXDEMOConnectionString”。

- 配置Select语句,如图18所示,从下拉框中选择“HEROES_XML”表,选择HEROID和HERONAME域。不要选择NOTES域。这里是直接的表导出而无须WHERE语句。可以使用一个ORDER BY语句来改变表的顺序。底部SELECT语句将会自己写上。

- 在下一页你将可以测试查询,保证你能够正确连上数据库。你可以从表19中看到结果集。

- 最后异步,通过选择HERONAME配置Repeater表,显示控件,HEROID为控件的值。图13。

- 切换回代码视图,你可以看到新的控件。你可以剪切和粘贴它到你的<div>标记。现在,将不会显示任何东西,所以你需要键入一些模板。在<asp:Repeater>控件中,加入HeaderTemplate代码。加入如下的代码:
| <HeaderTemplate> <h3>Available Roster:</h3> <ul class="HeroList"> </HeaderTemplate> |
- 下面,增加ItemTemplate。这将包括一个onclick事件来调用一个JavaScript函数,并且将被选的值的HeroID传递给它。我增加了一些函数如处理onmouseover和onmouseout事件。使用DataBinder对象来获取数据值。
| <ItemTemplate> <li class="heroItem" onclick="getHeroInfo(<%# DataBinder.Eval(Container.DataItem, "HeroID")%>)" onmouseover="this.className='heroItem_hl';" onmouseout="this.className='heroItem';"> <%# DataBinder.Eval(Container.DataItem, "HeroName")%> </li> </ItemTemplate> |
- 最后,增加FooterTemplate来关闭未排序的list。
| <FooterTemplate> </ul> </FooterTemplate> |
这样就完成了Repeater控件。你可以测试它来连接数据库获取数据。但是注意这里调用JavaScript会引发一个错误,我们将会在下一节中解决这个问题。
JavaScript: Ajax A-Go-Go
如果你曾经写过Ajax代码,那么这里就不耽误时间了。拷贝如下代码增加到<head>标记中。或者你可以将它作为一个独立的.js文件并且在Default.aspx中引用它。
Listing 12: JavaScript Code for Accessing DB2 Web Services
| <script language="javascript" type="text/javascript"> var request; function createRequest() { try { request = new XMLHttpRequest(); } catch (tryms) { try { request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (otherms) { try { request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (failed) { request = null; } } } if (request == null) alert("Error implementing Ajax functionality"); } function getHeroInfo(heroID) { createRequest(); var url = "http://localhost/Superpals/HeroData.asmx/getWithXML"; request.open("POST", url, true); request.onreadystatechange = showHeroInfo; request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.send("heroID=" + heroID); } function showHeroInfo() { if (request.readyState == 4) { if (request.status == 200) { var xmlDoc = request.responseXML.documentElement; var notesList = xmlDoc.getElementsByTagName("HERO")[0].getElementsByTagName("NOTE"); var len = notesList.length; var notesDiv = document.getElementById("notes"); //Clear Notes Span tag while (notesDiv.firstChild) { notesDiv.removeChild(notesDiv.firstChild); } var newSpan, newText; for (var n = 0; n<len; n++) { var newSpan = document.createElement("h3"); newSpan.className = "noteTitle"; var newTextVal = notesList[n].getAttributeNode("title").nodeValue + ": "; var newText = document.createTextNode(newTextVal)newSpan.appendChild(newText); notesDiv.appendChild(newSpan); var newSpan = document.createElement("p"); newSpan.className = "noteValue"; var newTextVal = notesList[n].firstChild.nodeValue; var newText = document.createTextNode(newTextVal)newSpan.appendChild(newText); notesDiv.appendChild(newSpan); } } else { var stat = request.getResponseHeader("Status"); alert(request.status + " | " + stat); } } } </script> |
它做了什么:
- “var request;”:全局声明的请求对象,在多个函数中被使用;
- “function createRequest()”:特定浏览器的XMLHttp初始化。(这个程序在微软IE和Firefox中运行)
- “function getHeroInfo(heroID)”:这是Repeater控件的onclick事件调用的函数。它形成一个向你早先创建的Web服务的请求,特别是HeroData的“getWithXML”。它然后通过POST提交HeroID,发送请求到showHeroInfo来处理。
- “function showHeroInfo()”:程序的主要代码。如果你已经使用了第一个Web服务,根据表而不是一个XML数据类型,那么函数将更加的长,更加的复杂。
| var notesList = xmlDoc.getElementsByTagName("HERO")[0].getElementsByTagName("NOTE"); |
正确的解析结果是Ajax程序的业务核心。这里DB2 9使用XML数据类型和查询语言简化了一堆过程使得你能够用极精简的代码来获取想要的数据并且传递给DOM。
在指定相关的XML数据后,代码已经比较清晰和明确了。在基于XML数据创建新的文档节点时,你仍然有一些选择。通过将重要的但是无关联的数据放置在一个XML域中,并且通过指定标题来结构化它,你能够遍历子节点,创建头部和主题而无须多余的异常处理。现在使用“getAttributeNode”来访问“title”属性。
在这里,我简单的使用了<h3>和<p>节点,可以被分开样式化。没有必要解析Notes域。没有必要增加单独的域处理。显然你能够使用不同的标记,如<div>或者<span>甚至是<ul>和<li>标记。
对于格式,增加如下一些代码到你的<head>标记来让页面更加整洁:
Listing 13: Styles
| <style type="text/css"> ul {font-family:Arial; font-size:.9em; } li { list-style:none; font-family:Arial; } h3 { font-family:Arial; font-size:1.3em} p { font-family:Arial; font-weight:normal; font-size:.9em} #notes { float:right; border-width:1px; border-style:solid; width:50%; padding:20px 20px 20px 20px;} #heroList { font-family:Arial; float:left; width:30%; padding:20px 20px 20px 20px;} .heroItem_hl { font-weight:bold; background-color:azure; } .heroItem { font-weight:normal; background-color:white; } </style> |
你的完整的Default.aspx页面如图14所示。

由于服务器端程序已经完成,现在可以浏览Default.aspx来检查结果了。
“Available Roster”可以直接从DB2 9数据源中获取数据。选择任何一个,右边将会通过一个C#Web服务调用显示你的XML域内容。每个英雄都有各自的属性,你可以使用一些处理方式来优化显示。
这就是你可以用到的DB2 9的新的XML功能特性。但是不仅仅是这一个。XML无处不在——DB2 9给予你掌握它的力量。



