返回首页
当前位置: 主页 > 网络编程 > 其他实例教程 >

从一个范例看XML的应用详解教程

时间:2017-02-12 22:25来源:知行网www.zhixing123.cn 编辑:麦田守望者

如果你已经看了Asp.Net Ajax的两种基本开发模式 这篇文章,你可能很快会发现这样一个问题:在那篇文章的方式2中,客户端仅仅是发送了页面上一个文本框的内容到服务端,而服务端的Web服务方法也只接收一个来自客户端的字符串类型的数值。而很多时候,服务端的方法期望接收的是一个自定义类型,或者是多个不同类型的参数。为了能够处理这种由一个字符串包含多种不同类型值情况,我们可以采用XML。

这篇文章将构建一个简单的图书查询页面,通过这个程序,我们将会看到XML、XSD模式验证、XSLT样式转换,以及Asp.Net脚本回调功能的一个综合应用。

数据库建立和数据访问

我们先看一下这个Web页面实现的功能:页面提供一些文本框供用户输入,包括书名、出版社、作者等信息,然后将这些信息发往服务器,服务器对数据库进行查询,然后返回查询结果。如果是通常的Asp.Net开发,完成这样的功能是很基本的要求,根本用不着我花时间写这些文字,但这里我们希望实现Ajax方式的效果,所以就需要解决引言中提出的问题。

如果你看过我的文章,那么应该知道我喜欢循序渐进的写作方式,这篇也是一样,我们先从数据库建立开始。由于数据库和数据访问并不是本文的重点,所以我只简单地描述一下步骤。在本地SQL Server或者直接在App_Data下新建一个数据库,起名叫SiteDB,然后建一个表Book,字段的设定如下:

随后填充一些范例数据,如果你想节约点时间,那么可以直接下载本文所附带的代码,在App_Data文件夹下包含有SiteDB数据库。

接下来我们在App_Code文件夹下添加一个SiteBLL.cs文件,本文用到的所有代码逻辑都包含在了SiteBLL类中,这么做显然是不妥的,但这里我们主要关注的是XML的应用,而非构架与设计,所以暂且就这个样子好了。很容易就能想到,我们要添加的第一个方法,会拥有下面这样的签名,它根据方法的参数查询数据库,然后以DataSet的形式返回结果:

private static DataSet SearchBook
    (string name, string author, string publisher, DateTime pubDate, decimal price)

如果要构建一个实际的查询,那么需要很大量的数据才能保证几乎每次搜索都能够获得到数据来提供演示,而实际上我们只添加了5条范例数据,所以让我们干脆将它们全部返回,而忽略这里的参数,但在实际当中,当然是根据这些参数来获得实际的返回数据:

private static DataSet SearchBook(string name, string author,
    string publisher, DateTime pubDate, decimal price)
{
    string connString =
        WebConfigurationManager.ConnectionStrings["SiteDBConnection"].ConnectionString;
    string provider =
        WebConfigurationManager.ConnectionStrings["SiteDBConnection"].ProviderName;

    DbProviderFactory factory = DbProviderFactories.GetFactory(provider);
    DbConnection conn = factory.CreateConnection();
    conn.ConnectionString = connString;

    DbDataAdapter adapter = factory.CreateDataAdapter();
    DbCommand selectCmd = conn.CreateCommand();
    selectCmd.CommandText = "Select * From Book";
    adapter.SelectCommand = selectCmd;

    DataSet ds = new DataSet("BookStore");
    adapter.Fill(ds, "Book");
    return ds;
}

这段代码没有什么好解释的,唯一值得注意的可能是我完全采用了面向接口(基类)的方式编写数据访问代码,这样将来如果更换为Oracle或者其他任何数据库,这里不需要更改一行代码,只需要修改下Web.Config就可以了。

XML应用 -- 单一字符串包含多种不同类型值

接下来我们对页面进行一下布局,如下所示:

控件的命名是自解释的,所以下面看代码应该不会遇到障碍,这里我就不再赘述了。需要注意的是页面上含有一个空的div标记,它用来承载我们的查询结果:

<div id="output"></div>

另外,“搜索”按钮是纯粹的HTML标记,不含有runat="server"属性,双击它,会在页面生成下面的javascript脚本段:

function btnSearch_onclick() {
    // ...
}

接下来我们要做的就是实现这个js方法,它的任务就是将文本框中输入的内容发往服务器。此时我们遇到了文章开头提出的问题,服务器期望的是5个参数,而且有字符串、数字、日期三种类型,而在客户端,我们只有一种类型 -- 字符串。因为javascript和C#显然用得不是一个类型系统,它们完全是两个领域。同时我们只发送一个参数,但要包含所有5个数值。对于现在以及和现在类似的情形,我将它统称为单一字符串包含多种不同类型的数值的情况,为了便于服务端(更宽泛点,叫程序)的处理,我们可以定义自己的XML。此处,我定义它的格式为:

<userInput>
    <name>书名</name>
    <author>作者</author>
    <publisher>出版社</publisher>
    <pubDate>出版日期</pubDate>
    <price>价格</price>
< /userInput>

有了这个格式定义,实现btnSearch_onclick()就非常的容易了:

function btnSearch_onclick() {
   
    var name = <%="document.getElementById(\"" + txtName.ClientID + "\").value" %>;
    var author = <%="document.getElementById(\"" + txtAuthor.ClientID + "\").value" %>;
    var publisher = <%="document.getElementById(\"" + txtPublisher.ClientID + "\").value" %>;
    var pubDate = <%="document.getElementById(\"" + txtPubDate.ClientID + "\").value" %>;
    var price = <%="document.getElementById(\"" + txtPrice.ClientID + "\").value" %>;
   
    var inputXml = "<userInput>" +
            "<name>" + name + "</name>" +
            "<author>" + author + "</author>" +
            "<publisher>" + publisher + "</publisher>" +
            "<pubDate>" + pubDate + "</pubDate>" +
            "<price>" + price + "</price>" +
            "</userInput>";
   
    var context = "Any data you want to pass !";
   
    ClientSearchBook(inputXml, context);
}

这段代码需要注意这样几点:

  1. 由于习惯问题,我给页面拖的是Asp.Net服务器控件,实际上,这里使用纯粹的Html Input标记就可以了,代码会更清爽一些,但是因为已经写好了,我偷懒了一下就没有改过去>_<、(但是使用服务器控件会有一个额外好处,就是可以使用验证控件,但是这里出于演示目的,我没有添加验证控件)。
  2. 这里的context和Asp.Net Ajax的两种基本开发模式 后面介绍的context作用一样,可以用来传递任何数据,这个值可以从调用成功或失败的回调方法中获得。
  3. ClientSearchBook()方法并没有实现,因为这篇文章我打算采用Asp.Net的脚本回调来实现,而不是用已经介绍过的Ajax Extension配合Web Service来实现,所以这个方法最后是由服务端生成的,这在后面会介绍到。现在只需知道它将inputXml发往服务端就可以了。

再次与Asp.Net Ajax的两种基本开发模式中介绍的第二种方式类似,我们实现onCompleted()和onFailed()这两个回调方法,它们将会在服务端生成的脚本代码中进行注册(后面会看到),当调用成功时调用onCompleted(),调用失败时调用onFailed()(这里我没有再演示context的使用了):

function onCompleted(result, context){
    output.innerHTML = result;
}

function onFailed(error, context){
    output.innerHTML = "Search Failed : " + error;
}

方法的实现只不过是将返回结果或者错误信息显示在页面的div标记中。

XML模式 -- 使用XSD校验客户端数据

我曾经听过这样一句Web编程的“谚语”――永远不要相信客户端发来的数据。意思就是说即便你添加了客户端的表单验证,仍然要在服务端对客户端发来的数据进行验证。在本文的例子中,我们接收的是一个XML字符串,那么如何对它进行验证呢?我们可以使用XML模式(XML Schema)来对它进行验证,XML模式文件的后缀名为xsd。对于XSD有这样一个很好的类比:就拿数据库的表定义来说,如果你定义的XML是表的列名,那么XSD就规定了列的类型(int还是bit,或者varchar)。

手工编写XML模式会很精细,但对于复杂的XML文档来说是很费力气的。在VS2008中,有一个内置功能,可以由XML文档推断出它的模式,尽管推断出的模式往往不够精准,但我们可以对推断出的模式进行一些修改,在大多数情况下就可以得到我们想要的模式。具体的做法是:创建一个符合预期输入的XML文件,用VS2008打开这个文件,然后在菜单栏选择“XML”-->“Create Schema”,再对这个生成的模式进行修改,最后保存在站点目录下,这里我将它保存为了userInputSchema.xsd:

<?xml version="1.0" encoding="utf-8"?>
< xs:schema attributeFormDefault="unqualified"
              elementFormDefault="qualified"
              xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="userInput">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="name" type="xs:string" />
                <xs:element name="author" type="xs:string" />
                <xs:element name="publisher" type="xs:string" />
                <xs:element name="pubDate" type="xs:date" />
                <xs:element name="price" type="xs:decimal" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>
< /xs:schema>

------分隔线----------------------------
标签(Tag):XML应用
------分隔线----------------------------
推荐内容
猜你感兴趣
博聚网