Print Search
帖子排序:    
帖子发起人: 九九归一   发起时间: 2005-08-09 09:43 上午   回复: 0
zhangjj 离线,最后访问时间: 2005-8-9 12:17:18 九九归一



发帖数前75位
男
注册: 2005-08-09
合肥和谐软件有限公司
发 贴: 3
.NET 中快速开发功能强大的Web应用程序
 2005-08-09, 09:43 上午

本文发表于《程序员》杂志2003年第三期

.NET 中快速开发功能强大的Web应用程序
                                  ——介绍一组Web控件及Web工程应用架构

合肥和谐软件/张纪九  马可  杨波

_____________________________________________________________________
关键词  应用架构  .NET framework  ADO.NET  ASP.NET  XML Web Services  Visual Studio.NET  Visual C#.NET
_____________________________________________________________________
摘  要  本文主要介绍在.NET framework下使用Microsoft Visual Studio .NET开发Browser-Server应用程序的技巧和捷径。本文涉及的Web控件及Web工程应用架构,已在国家级科技创新项目“具有实施向导的ERP系统”中成功应用,实现了快速高效开发功能强大界面友好的企业级Web应用程序,Demo Web应用程序:WWW.hexiesoft.NET
_____________________________________________________________________
本文目标
了解 Microsoft .NET应用程序典型结构及开发技术
了解如何利用控件及应用架构进行Web程序快速开发
前提条件
熟悉编程概念(包括类和属性)
熟悉各种结构(包括多层和多服务器结构)
熟悉 .NET framework下开发(Web应用程序开发)

1. .NET framework下使用ADO.NET及XML Web Service的三层应用程序结构
    开发基于.NET framework应用程序的一种设计方式是使用ADO.NET及XML Web service,将数据库的访问单独分给一个组件,该组件将把数据返回到前端应用程序,如图1。
 


          图1 .NET下ADO.NET及XML Web Service的三层结构
1.1 何时使用此技术
  使用 XML Web service 的三层应用程序适用于基于 Web 的应用程序或 Microsoft Windows 应用程序。本文主要介绍前者。如果需要桌面应用程序的丰富功能,而用户连接自多个不同的位置,并通过 HTTP 界面访问数据,则很适合使用此技术。
1.2 典型的实现方式
  要创建三层ADO.NET—XML Web service 应用程序,通常采用以下开发技术:
  常用 SQL 驻留在 XML Web service 中,在服务器上构建数据集,并将其作为 XML 流返回到客户端,它们在这里又可以重新被构建为数据集。
  可以将从 XML Web service 返回的数据集直接绑定到窗体的控件中。
  可以使用从 XML Web service 返回的数据集手动将数据加载到窗体的各种控件中。
1.3 优点
  使用 XML Web service 的三层应用程序具有以下优点:
  因为可以使用数据绑定将 ADO.NET 数据集直接与用于构建用户界面的很多控件连接,所以开发工作就变得简单而快捷。这有助于迅速建立并运行应用程序的基本功能。
  用户可以从能连接到 Internet(或 Intranet)的任何地方运行应用程序。
  可以在某个中心位置更新数据库访问层。如果对此层进行简单的代码更改,则无需重新向客户端分发组件。
1.4 缺点
  此设计的缺点是它并没有分离业务规则,而只是分离了数据层,表中的列名称也没有被提取到类中。
  所有字段名称均在源代码或控件属性中硬编码。
  通过 HTTP 界面进行访问比直接连接数据库要慢。
2. 使用Web工程架构快速构建企业级应用程序
2.1 架构所用数据结构简介
  从上面介绍的三层应用程序结构中我们可以看到,要构建具有一定缩放性的企业级应用程序,就必须对不同层次的数据结构作出良好的定义。在企业级应用程序中,系统一般可被划分为若干个模块,每个模块又可被划分为若干个子模块,当这种划分达到每个子模块均可完成一个相对独立完整且定义清晰的子功能时,我们就可以在一个Web页面(在.NET framework下一般是一个或多个.aspx页面)中完成这一项功能,对这样的模块我们在下文中称其为末级模块。对于上面的父子模块关系,树型结   构是一种合适的数据表示,在数据库中我们用一张表[基础信息_软件菜单]来表示这种结构。
  从[基础信息_软件菜单]的字段定义中我们可以看出,每个模块对应着一个菜单,菜单之间的父子关系直接反映了模块之间的父子关系,因此下文中均使用“菜单”来指代上文提到的“模块”。菜单的树型结构是通过为每个节点设置一个指向其父节点的指针来实现的,在表中用外键为[菜单编号]字段的[组别]字段来表示每个菜单的父菜单。对于末级菜单(末级模块对应的菜单),[文件名称]字段保存菜单对应Web页面的URL。其他字段说明如下:
  [菜单编号]:每一个菜单的标识。
  [菜单名称]:每个菜单的名称,在菜单树以及菜单图标中都会用到。
  [层次]:用于表示菜单的在目录树中层次,规定根节点层次为0。
  [开关]:菜单及其子菜单在目录树中是否显示,即菜单对应的功能模块是否可用。
  通用程序架构中的安全模块主要通过以下几张表来完成:[基础信息_用户口令]、[基础信息_岗位编号]、[基础信息_岗位菜单]、[基础信息_软件菜单]。[基础信息_用户口令]中存放用户登陆时输入的用户名及密码,[基础信息_用户口令] .[岗位编号]字段则保存用户的岗位以授予其不同的权限。[基础信息_岗位编号]表中保存各岗位的名称及其编号。架构通过[基础信息_岗位菜单]表来获得不同岗位所能看到的菜单,实际上该表保存了岗位和菜单之间的多对多的关系,另外该表还保存了每个岗位所能使用的某个菜单上的按钮,各表间关系如图2。
  另外设置[基础信息_参数规则]表记录架构的参数,比如是否提示用户设置首页以及是否下载浏览器的最新版本。
  从上面的数据库设计可以看出,系统中尽可能将数据和代码分开。这样做的好处是很明显的:
  对于数据的管理直观而方便(通过数据库本身提供的管理工具)
 


            图2 登录部分表关系图
  可扩展性好,例如新增菜单时并不需要修改主架构中生成菜单树的代码,代码可移植性及通用性强。
  安全性好。数据库本身能够提供较好的安全管理机制。
2.2 架构页面简介及功能分析
  总体架构包括用户登录(Login.htm)和主界面(Default.aspx)两个部分。


 


             图3 用户登录采用窗体式验证
  用户登录采用窗体式验证,用户未登录时访问其他页面都将被自动转向登录页面,如图3。
  主界面分三个部分,采用Windows资源管理器风格的界面,从左至右划分为三个页面:菜单目录树(Left.aspx)、菜单详细信息(DisplayDetail.aspx)、菜单列表(MainFrame.aspx)。
2.3 如何在架构中新增模块
  从上文中对数据结构的分析以及框架页面和功能的介绍我们可以看到新增一个功能模块实际上是新增一个或多个菜单,而所需做的工作仅仅是修改数据库中的[基础信息_软件菜单]等数据表。下面我们一步一步说明如何利用Visual Studio.NET编辑工具新增一个模块HelloModule到项目中来。
  1)在Visual Studio .NET编程环境中打开hexiesoft,在“解决方案资源管理器”中找到项目hexiesoft。
  2)在项目hexiesoft中添加一个新的文件夹HelloModule。
  3)在HelloModule文件夹中添加新的Web窗体HelloWorld.aspx,打开其设计视图。
  4)在HelloWorld.aspx的窗体左上角放置一个Label型的Web窗体控件,将“Text”属性改为“Hello World!”如图4。
 


              图4 HelloWorld.aspx示例
  按“Ctrl+S”保存项目,然后点击菜单“生成|生成解决方案”以编译我们新加入的页面。
  5)打开SQL Server 2000的企业管理器,在hexiesoft的数据库中找到数据表[基础信息_软件菜单],打开数据,加入一条新的记录,对应于我们的“HelloModule”文件夹,注意只要输入“组别”、“菜单名称”、“层次”、“顺序”、“开关”五个列的值,分别为“0、HelloModule、0、1、1”。输入完后,在其他记录的空白处点击鼠标左键,让系统生成此行记录,注意此时我们没有填入内容的列也由系统自动生成了,特别注意一下生成的“菜单编号”的内容,此处为399,不同的机器会有不同,如图5。
  类似地,再加入一行记录,对应于页面“HelloWorld.aspx”,输入“组别”为上一行记录中由系统自动生成的“菜单编号”(此处为399,不同的机器会有不同),其他列“菜单名称”、“层次”、“顺序”、“开关”、“文件名称”的值,分别为“HelloWorld、1、1、1、HelloModule/HelloWorld.aspx”,确认在数据表中输入了两行记录后,关闭SQL Server 2000的企业管理器。
 


            图5数据表[基础信息_软件菜单]示例
  6)在数据库中加入了我们的菜单HelloModule和页面HelloWorld.aspx,并不能立即看到它,因为还得赋予用户以权限才能查看,可以利用我们已经编好的一项菜单来完成。在IE中打开hexiesoft系统,运行“基础信息系统”|“用户权限设置”中的“设定岗位菜单”,可以看到我们的“HelloModule”已经出现在菜单树中,如图6。
 


              图6 “设定岗位菜单”示例
  7)在左边的菜单树中点击“HelloModule”,并在右边岗位列表中找到“系统管理员”,钩上相应的检查框,再点击上边工具栏里的“设置”,即将运行HelloModule菜单的权限赋给了管理员。
  8)关闭“设定岗位菜单”对话框,关闭Internet Explorer,然后重新启动Internet Explorer,打开hexiesoft,可以发现这时“HelloModule”已经出现在我们的菜单系统中,其中包含了一个子菜单,双击这个子菜单,可以弹出页面HelloWorld.aspx。
2.4  如何在Web页面中传递变量
  上一节中作为示例我们在架构中新增了一个HelloModule模块,本节将介绍如何在Web页面中传递变量。
  我们先来介绍ASP.NET中一个很重要的概念——服务器控件。
  首先让我们考虑一下基于Web的应用程序和基于Windows的应用程序有哪些重要区别。基于Web的应用程序采用Browser—Server的体系结构,客户端的网页浏览器和服务器端进行数据交换是通过HTTP协议进行的,根据这种协议,客户端的请求得到了服务器端的响应之后,两者之间的连接就被关闭。这种不保持连接的工作方式决定了我们很难为每一个客户端或每一个Web页面维持一个状态。除此之外,由于客户端程序实际上是HTML格式的网页,而HTML是一种描述式的语言,其主要描述的内容是界面对象及其格式。所以在以往诸如ASP,PHP等脚本语言中,只能在服务器端通过Request对象来获得查询字符串或表单内容,从而了解用户的操作以及输入的数据,进而给出新的响应。在Windows应用程序中,每个程序有自己独立的内存空间,每个控件并不像HTML对象那样被严格定义而是可以根据不同的需要维持各自的状态。另外基于Client—Server结构的应用程序可以采用不同于HTTP的通讯协议维持客户端状态。
  ASP.NET中提出的服务器控件概念实际上就是为每一个控件保持一个状态,虽然其实现机理仍然是通过Request对象中的表单内容来记录控件状态及产生的事件,但是ASP.NET提供了一套比较完整的机制来自动完成这些工作。
  Visual Studio.NET提供了一些常用服务器控件。在我们下面的程序中还要用到Microsoft网站提供的Internet Explorer Web Controls,其中包括Toolbar控件(工具栏)、TabStrip控件(多页面标签)和TreeView控件(树型控件)。
  编写我们的新增模块时还需要解决的一个问题就是如何传递变量。这主要包括服务器端和客户端之间的变量传递、页面与页面之间的变量传递。前文中我们已经提到HTTP协议具有无状态的特点,在服务器端可以为每一个会话建立一个Session对象,但却无法为每一个页面维持一个对象,在ASP.NET中为了解决这个问题为每个页面设立了一个ViewState属性来维持页面级变量。但是对于不同的页面之间存取ViewState中的变量却并非易事,从客户端更是无法直接访问ViewState属性,所以我们必须谨慎地定义需要传递数据的位置和传递数据的方法,在保证程序正确性的前提下一方面最大限度地减少通讯量,另一方面尽量保持传递方法的一致性。我们系统中用到的页面之间的变量传递主要采取五种方法:
查询字符串
  当打开一个页面时,需要向其传递数据量非常小的参数,可以采用查询字符串(QuerryString)的方法。例如打开一个显示用户资料的页面ShowUser.aspx,通过ShowUser.aspx?id=UserName形式的URL,高效地将参数传递给页面。
表单
  如果某个页面要传递的数据量比较大,采用查询字符串就比较累赘了,而且速度也慢,这时易采用表单。表单可以看作是一个存放网页数据的容器,当需要将一组数据传给另一个页面作处理时,通过修改表单的“action”属性,然后提交它,所需数据就会传到目标网页。
Session变量
  查询字符串和表单都和客户端有联系,有时数据仅仅在服务器端有用,例如用户登录后的用户名要一直保留,以便在需要的时候查验,这时候采用Session变量,可以面向不同的会话保存不同的数据,从而在同一会话的不同页面中共享数据。
Application变量
  当需要保存一个与系统有关的数据时,采用Session变量就不行了,因为Session仅仅与会话有关,不同的会话有不同的Session对象。一个最简单的例子是计数器,我们要保存已经访问过系统的总人数,当一个用户注销后,与他有关的Session变量也随即消失,所以计数器不能保存在Session变量中,这时就需要用到Application变量,所有的Application变量保存在Application对象中,该对象的生存期自服务器端应用程序第一次启动直至程序中止,不会受到新建立会话的影响。
Cache缓存
  有时需要存储大量的数据,这时使用Session和Application变量就会效率非常低,因为它们设计时都是用来存储小批量数据的。Cache对象存在于服务器端的内存中,充分利用这一特性,往往对提高程序效率大有帮助。

3. 自定义控件及类库
3.1 DataGridPro控件
  在前文中介绍如何编写新的模块时我们曾经提到一个用于显示数据的自定义表格控件DataGridPro,下文中我们将对它进行详细说明。
  如果我们要在HTML网页上用表格形式显示数据如图7,相信并不是一件难事。
  但是想要获得诸如鼠标拖动改变表格列宽、滚动表格时保持表头固定、单击选中表格一行等在一般Windows程序中极易实现的表格功能,就不是那么容易了。这主要是因为在HTML网页上生成表格必须通过标准的HTML语言,而动态改变表格的外观则需通过对DHTML提供的对象模型进行脚本编程来实现。由于受到对象模型本身的限制,我们必须通过编写复杂的脚本才能实现在Borland C++、Visual Basic或Delphi中提供的表格控件所具有的基本功能。
  本节将介绍一个在Web页面中实现数据表格常用功能的控件DataGridPro如图8所示。DataGridPro基于.NET Framework中用户自定义控件技术实现。下面分别从DataGridPro在服务器端和客户端使用的技术和提供的功能来作以介绍。
 


             图7  HTML网页一般表格形式
 


             图8  DataGridPro控件
  在服务器端主要实现表格数据的缓存和对选中行的保存。
1) 表格数据的缓存
  当表格要显示的数据量很大时,一次性全部加载需要很长的时间。这其中主要涉及到两个过程:从数据库中取数据和根据数据生成HTML格式的表格并传输个客户端浏览器以显示给用户。.NET Framework提供的标准服务器控件DataGrid提供了分页来解决这个问题。
  DataGridPro 采用了一种类似分页但却令用户觉察不到分页的加载数据方法,如图9所示。具体地说就是在第一次加载数据时仅仅加载第一页的数据,当用户需要浏览更多数据而拉动垂直滚动条时,引发页面提交动作并请求服务器加载更多的数据。DataGridPro中实际上包装了DataGrid控件,而每次加载页面实际上是通过DataGridPro提供的分页功能来实现的:设第i次页面大小为sizei则第i+1次加载时页面大小为sizei+1=sizei+size1这样做实际上使得上面所提到的在表格中显示数据所经历的第二个过程并非一次完成而缩短时间。由于表格数据可能会被多次加载,DataGridPro自动将数据源缓存在服务器的内存中,这样不必每次都从数据库中取数据而减小了表格显示数据所经历的第一个过程需要的代价。
 


            图9  DataGridPro加载数据方法
  2) 选中行集的保存
  为了实现用户单击选中一行的功能,必须将用户选中的行集保存在页面中。但是由于HTTP协议是不保持连接的所以HTML页面是无状态的,Session对象虽然为每个用户会话提供了状态,但是页面状态的保存在过去的脚本语言中仍然是个问题,那时程序员通常使用隐藏的输入文本框或查询字符串来维持页面状态。.NET Framework中为隐藏的文本框保存页面状态提供了专门的函数Page.RegisterHiddenField(),同时也通过隐藏文本框实现了一个用于保存页面状态的对象——Page.ViewState.这样对用户单击一行的处理就可以在服务器端完成并将处理结果(选中行集)以数组形式保存在ViewState中。
  DataGridPro在客户端主要实现对客户操作的一些动态响应,包括鼠标拖动改变表格列宽、表格内容滚动时表头位置始终固定、表格大小和位置的设定、响应用户双击事件、设置标示列方便用户选择等。
  DataGridPro采用了behavior技术来实现。Behavior是一种将对象行为和函数封装起来的组件。
  3) 鼠标拖动改变表格列宽
  实现这一功能首先要能够确定鼠标的位置是否在表格列分割线附近,这是通过mousemove事件中给出的offsetX来进行判断的。由于在DHTML中我们可以动态改变对象的属性,所以可以根据鼠标移动的相对距离来确定表格新的列宽并实现动态改变。
  4) 表格内容滚动时保持表头位置
  DataGridPro中使用如下办法:在behavior中为表格复制一个新的表头。这个表头和原有表头格式及内容完全相同,但它被放在一个新建的HTML元素DIV(是用来划定一部分区域并在其中显示所包含的HTML元素)中,并且其zIndex只比原有表格的zIndex大,
  5) 响应用户双击事件
  解决这个问题的关键是如何在存在双击事件的情况下先提交双击事件而后再提交单击事件。DataGridPro中为单击事件的提交设置一个延时(通过一个客户端的定时器来实现),这个延时至少要长于双击事件比单击事件延迟的那一段时间。这样我们在服务器端可以分别相应单击和双击事件并提供给DataGridPro的用户。
  DataGridPro实现了数据表格的许多常用功能,对它的使用却是十分简单而方便的。由于DataGridPro本身是用户自定义控件,在编写程序时可以使用设计视图下的拖放操作来新增一个DataGridPro,其数据绑定与DataGrid控件非常相似,新增功能则完全可以通过对其属性的访问和事件的响应来获得。
3.2 DataTransformService组件简介
  我们知道在.NET framework提供的类库中对数据库的操作一般是通过DataSet来实现的。DataSet可以非常方便的转化为XML文档。但是在实际应用中,我们往往需要将DataTable中存储的数据表以多种数据格式输出。DataTransformService是一个用Visual Basic.NET编写的数据转换组件。其输入为DataTable的实例,输出可为Access(*.mdb)、Excel(*.xls,*.csv)和XML(*.xml)等文件格式。DataTransformService组件利用SQL Server本身提供的DTS服务可以方便快捷的实现数据的分发和转存。
3.3 通用类库简介
  .NET framework提供了许多功能强大的类库,但是对于开发具有多窗口、多框架(frame)且以SQL Server作为后台数据库的Web应用程序,就需要有针对这种程序特点的类库来提供支持。下文中将介绍的JSUtil、UIUtil、DBShell等类分别封装了对客户端脚本、用户界面、SQL Server数据库的访问。
通用类JSUtil提供一系列静态函数,方便用户在服务器端注册客户端的JavaScript脚本;通过在服务器端注册客户端脚本来执行一些客户端的脚本操作,如关闭窗口、弹出网页对话框、提交表单等等。
  通用类UIUtil提供对用户界面、Web窗体控件进行操作的静态函数,例如改变Toolbar按钮文字及图片等。
  DBShell封装了对SQL Server数据库的存取操作。我们知道使用System.Data.SqlClient命名空间中的类来存取SQL Server数据库一般来说只需要连接字符串和SQL语句即可。DBShell就是一个封装了对SqlConnection、SqlCommand、SqlDataAdapter、DataSet的初始化及存取操作的类,只需在DBShell的构造函数中提供一次连接字符串,以后执行SQL语句仅提供语句本身即可。所有取得的表存储于DBShell的theDataSet属性中,使用起来非常方便。

4. 结束语
  “工欲善其事,必先利其器。”本文所介绍的是Hexiesoft.NET工程架构,它是一款Web控件组合和Web工程架构的集成包(含全部源编码和注释),用于基于.NET下的Web应用程序开发,适合软件项目开发和软件产品制造,可以有效地加快项目开发和提高产品质量,是国内最新的专门针对Web开发的集成包,为采用Visual  Studio.NET开发Web应用程序的最佳解决方案。
  利用本文介绍的Hexiesoft.NET工程架构不仅可以快速开发具有层次结构的企业级Web应用程序,缩短系统分析、主程序构建、人员培训等过程,提高开发进度,还能够为应用程序提供简洁明快的风格和方便友好的界面。由于该工程架构提供的是最基本的支持功能,所以在开发ERP、CRM、SCM、PDM和OA等多种信息管理系统时都可以直接应用,并且完全能够重用。
  采用统一的架构系统,使Web工程的模块化大大提高,有利于划分任务;多人协同作业,从另一个方面又提高了生产率。充分而恰当的利用这些工具,应该针对不同应用的特点合理使用。
  本文所提及的Web应用程序Demo是Hexiesoft.NET工程架构在ERP项目中的应用实例,欢迎您访问.NET下的Demo Web应用程序:http://www.hexiesoft.net/  用户名(U):guest   密码(P):guest  。

IP 地址: 已记录   报告
合肥微软技术中心社区 » 技术讨论区 » .NET技术相关 » ASP.NET » .NET 中快速开发功能强大的Web应用程序

Powered by Community Server Powered by CnForums.Net