NET移植案例学习:建造Web站点 |
||||||||||||||
本文要求你熟悉Visual Studio 6.0,ASP和IIS 难度:2 摘要:当收集客户对Visual Studio .NET beta版反馈的网站需要升级的时候,Visual Studio开发小组发现这是一个使用.NET技术来开发一个真正的网站的好机会。本文描述了移植beta.visualstudio.net站点的过程,说明了如何使用ASP .NET和.NET框架将原来用Visual Basic 6.0和ASP开发的,发布在Microsoft Internet Information Services (IIS) 5.0上的组件移植到.NET平台下。还将介绍技术的选择和检查有效性、安全、认证等问题,并对现存的和新的用JScript 及ASP .NET开发的用作移植的组件作必要的解释。 Visual Studio开发小组设计了从测试站点得到用户反馈的机制,这是Visual Studio .NET beta版的一个部分。为此开发组在开发环境中增加了一个LAME按钮,它能帮助用户提交对这个产品的任何意见,包括对错误信息描述和菜单设计的意见等(参见图1)。开发小组还设计了跟踪用户如何使用产品的机制。产生的日志文件能帮助开发组进一步确定用户的需求。开发组用http://beta.visualstudio.net这个站点来收集这些信息和用户发现的漏洞,并向用户发布升级信息。 ![]() 图1 LAME按钮 这个Web站点的以前使用基于Microsoft Internet Information Services(IIS)5.0的Visual Basic? 6.0和ASP开发的。随着.NET产品的不断成熟,开发组希望通过在一个真实的开发环境中使用他们以获得第一手的体验,所以决定将这个站点移植到Visual Studio .NET和Microsoft .NET框架下。 通过自己的亲身体验,开发组对产品有了进一步的认识,为其他开发者充分利用.NET平台和Visual Studio .NET提供了很好的范例,还了解了哪些开发技术在Visual Studio .NET中仍然可以使用。 在这篇文章中,我将介绍将这个Web站点移植到.NET平台时使用的一些技术,得到的教训,并提供一些技巧来帮助你将应用程序移植到.NET平台。 原先的站点设计 这个跟踪站点由三个独立的Web站点组成。普通用户可以通过公众站点登陆、报告产品漏洞、上传日志文件、查看升级信息和已知的问题。Microsoft的员工可以通过内部网访问镜像站点无须通过公司的防火墙。Beta版的程序管理员可以通过管理站点得到测试网站的清单,管理站点的内容,配置站点其它的信息。 这个Web站点原先是用Visual Basic 6.0,ASP, Windows 2000和SQL Server? 7.0建立起来的。那时候,Visual Studio .NET和.NET框架是作为技术预览被发布的,用它来建造这个站的模块还显得不成熟。因此,我们用了Visual Studio和Windows2000的技术来建造这个站点的。 这个站点的体系结构符合Windows DNA 2000应用程序设计模型。我们用Active Server Pages 3.0开发了客户端的UI,并发布在IIS5.0上。这个程序的逻辑和数据访问代码在一个用Visual Basic 6.0写出的ActiveX DLL中,并注册到了COM+中。Visual Basic使用ActiveX Data Objects (ADO)来访问SQL Server 7.0数据库。图2 说明了这个站点基本的体系结构。 ![]() 图2 测试站点的体系结构 当开发组考虑如何将这个站点移植到Visual Studio .NET Beta 1的时候,他们决定只修改外部的客户站点(我将在下部分解释为什么这么做)而不修改管理站点。升级外部站点能实现他们获得第一手资料的愿望,并为客户提供了一个如何在.NET下开发软件的范例。 移植方法的选择 将站点移植到Visual Basic .NET和.NET框架的第一步是看看有哪些方法可供选择。现在有三种方法可以使用: · 将站点和Visual Basic 6.0的组件移植到ASP .NET和Visual Basic .NET · 将站点移植到ASP .NET,再用COM+ interoperability与现存的Visual Basic 6.0组件通讯 · 不改变现存的站点,而通过增加用ASP .NET和Visual Basic .NET写的新的功能模块来扩展站点的功能 在开始开发之前,开发小组确定了利用.NET的哪些功能模块来替代网站中复杂的,且有时会有问题的代码,并增加一些新的功能。具体的讲,他们希望按下面的要求重建网站: · 用ASP .NET认证来替代原来的用户安全机制 · 用ASP .NET Web Form确认控件来替代客户端用于报告产品漏洞和描述缺点的确认逻辑 · 用ASP .NET Web Services将Microsoft其它的网站溶入beta版产品漏洞报告体系中 · 利用.NET框架的本地化功能建造一个可以很容易实现本地化的Web站点 · 利用ASP .NET向用户提供个性化的菜单和横幅图片 为了充分利用这些特点,开发组决定将ASP页面移植成ASP .NET页面。他们将不移植现存的Visual Basic 6.0的ActiveX组件,而是创建新的Visual Basic .NET组件来实现Web Service和本地化。 现在让我们看看为了完成移植,对这个网站到底做了哪些修改。 结合ASP .NET认证功能 移植的第一步就是用ASP .NET中基于cookie的认证机制来替换原来的客户安全机制。这种安全认证机制首先出现在PDC技术预览中,并在Visual Studio .NET Beta 1中得到了发展。它的目标是确定谁在访问网站,而不是阻止用户访问。因此,开发组修改了成员资格系统,帮助用户注册到Web站点,并且在以后的Beta版产品中可以继续使用。 识别每个访问者的目的是跟踪他们报告的漏洞和缺点,并与他们进行必要的交流,以彻底解决问题。除了把用户的反馈送到特定的测试站点,用户还可以定制这个站点,以满足自己的需要,帮助客户将注意力集中在他们需要的信息上。把用户和他们感兴趣的内容联系起来能帮助站点管理员了解用户对什么问题最感兴趣。大多数测试站点包括了Visual Studio .NET和.NET框架各个方面的内容,允许用户访问站点上所有的文档,但某些用于特定方面(比如Visual Studio .NET IDE shell整和)的测试站点利用过滤器向客户只提供他们感兴趣的文档。 原先使用的认证方式使用一个ASP服务器端文件和一个Visual Basic组件所提供的方法,验证来访者所提供的用户ID和密码是否是数据库的成员。这个文件提供了可重用代码来完成安全检查,但这就意味着这个文件需要被包含在每一页的开头,才能保证这一页不会被未经过认证的用户打开。在每一页包含这个文件给管理员配置不需要安全保护的页带来了麻烦。 在ASP .NET中实现认证是很容易的,因为基于cookie的认证通过将站点的文档存放在某一个特定的文件夹实现了对文档的保护。当用户企图访问这个受保护的文档时,.NET框架将自动判断用户是否经过了认证。如果用户未被认证,.NET框架会把这个未经认证的请求重定向到某一个特定的HTML表单,让用户输入认证信息,并提交这个表单。如果用户得到了认证,.NET框架会产生一个可以辨别用户的cookie,并重定向到原先的请求页面。.NET框架还提供了一些类来帮助我们与认证过程交互和访问保存在cookie中的认证信息。 我们可以用Web站点的config.web文件来配置ASP .NET的认证体系。这个配置文件包含了一个用于指定认证方式的块、该块指明了HTML登陆表单的URL和密码的格式。图3是一个设置基于cookie的认证的config.web文件。 Web站点上原来的那种安全认证方式为每一个访问者唯一确立了一个对话ID。因为已经生成了这个ID,所以我们在移植认证过程不要改动现存的代码。ASP .NET认证机制将把未经认证的用户重定向到登陆页,让用户提交信用证。一旦提交了登陆页,用户ID和密码将被确认,还将产生一个会话ID。 实现ASP .NET认证体系只要修改原来的登陆页面的两个地方。我们没有向客户的cookie写入会话的关键字,而是使用了ASP .NET认证cookie,将它的值设为会话的关键字。然后通过CookieAuthentication 类的RedirectFromLoginPage方法将用户重新引导到原先的请求页。在接下来的请求中,将通过.NET框架的HttpContext.User类来访问会话ID。图4显示的是修改后的登录认证检查。 除了提供了一种更安全、更容易实现的安全认证体制外,ASP .NET认证体制还可以区别对待认证过的和未经认证的内容。因为保护的范围是由config.web文件中的目录结构决定的,所以只要把内容移出受保护的文件夹就可以取消对内容的保护了。 为了让认证机制能发挥作用,所有需要认证才可以访问的文件的扩展名应改为.aspx(ASP.NET文件的扩展名)。正如你将在下面看到的,这是一个相对简单的过程。 将ASP代码移植到ASP .NET 开发组希望在移植这个Web站点的过程中,能尽可能地少写代码,以减少产生漏洞的可能。在这部分,我将向你说明将ASP页面移植到ASP .NET最简单的方法是什么。但使用这种方法不能充分利用ASP .NET的新特点,只能建立一个能在ASP .NET下运行的站点。 许多页面需要做三四个标准的修改后才能正确运行。最常见的修改是要删除Set关键字。.NET框架和底层的common language runtime (CLR)把任何东西都当作对象处理,所以删除了Set这个关键字。下面这段代码取自原先的站点:
应该改为 :
另一个常见的改动是,在ASP页中引用一个对象时,要明确指定这个对象的默认属性。CLR和ASP .NET不再支持不传递参数的默认属性。不幸的是,尽管明确指定属性的值可以增加代码的可读性和可持续性,许多开发者更愿意利用默认属性的特点而不打出值。在这个Web站点中,当需要使用ADO记录时,默认属性经常被使用。原来的ASP代码像这样:
第三种常见的修改是改变类型转换函数的使用方式。再ASP .NET中,VBScript的类型转换函数被加到了.NET框架中。这个变化要求下面的ASP代码
转变为:
最后一个常见的修改是将调用Response.Write方法的格式改为ASP .NET中的方法调用格式。在VBScript,调用不返回值的过程时,不需要用小括号把参数括起来。但在ASP .NET中,所有传递到方法中的参数都要用括号括起来。在原来的站点中,在很多地方都调用了Response对象的Write方法,而且都没加小括号。为了将站点移植到ASP .NET,有必要将下面这段代码: <% Response.Write "Thank You!" %> 改为: <% Response.Write("Thank You!") %> 在对原来的ASP页面做了这些修改之后,这个Web站点就可以运行在ASP .NET下了。移植工作只要用两周就可以完成了。为了知道什么地方需要作修改,开发组应用Visual Studio .NET IDE新建了一个新的Visual Basic Web应用程序,将现存的ASP文件的扩展名都改为.aspx,并把它们加到工程中。一旦页面在IDE中显示了出来,Visual Studio .NET就高亮显示出语法,列出要作修改的地方,帮助我们这样发现编译期错误。 LAME报告和验证控件 在移植过程中,开发组决定修改数据输入页以充分发挥ASP .NET检验控件的优势,并降低现存代码的复杂度。当用户想提交一个LAME报告时,他们在点击错误对话框(帮助文档的反馈链接)上的LAME按钮,或者是工具栏上的Feedback按钮之后,在Visual Studio .NET IDE中会见到一个页面。为了将检验控件整合到LAME输入页,有必要重写这些页,并充分利用ASP .NET Web Form技术。 Web Form检验控件提供了一套独立于浏览器的校验函数,而不需要你在客户应用程序中用脚本语言写代码。这个控件可以在低版本的浏览器中使用(包括Microsoft Internet Explorer 4.0以前的版本和Netscape 5.0以前的版本),但需要利用服务器来检查控件的值并返回结果。当发现高版本的浏览器(Interne Explorer 4.0及其以后的版本和Netscape 5.0及其以后的版本)时,验证的主要步骤是在向服务器发送数据之前,在客户端完成的。在使用该版本浏览器时,如果被提交到服务器页面企图欺骗或绕过验证规则,服务器端的验证仍将进行。 Figure 5. 原来的LAME入口页中的验证逻辑的目标很简单:要求用户在提交表单之前已经在某些字段上填了值。尽管目标很简单,但它需要类似于图5中的Jscript代码的客户端脚本代码。 除了需要在客户端用脚本语言进行验证,还要在服务器上增加验证逻辑,以防止用户绕过客户端的验证并提交无效数据。使用了ASP .NET验证控件后,可以用Required,Compare和 RegularExpressionValidator等控件替换这些验证逻辑。这样不仅可以从页面中删掉很多Jscript代码,而且可以利用RegularExpressionValidator控件来加强验证。但当发现了高版本的浏览器时,仍将向客户端发送Jscript代码,这样就可以在提交到服务器进行验证前进行客户端验证,。不同处在于开发组不需要编写Jscript代码,验证控件会自动生成合适的代码。 当提交漏洞报告或一般的LAME报告时,需要同时提交所使用产品的版本。在大多数情况下,用户可以从下拉列表中选出版本号,而唯一的验证就是检查用户是否选择了一个版本号(参见图6)。但在某些情况下,比如未列出所用的版本时,用户需要手动输入版本号。在这种情况下,可以用两种格式来输入版本号,在提交到服务器前将检查格式是否正确。用来完成这种验证的Jscript代码可能很复杂,但如果使用RegularExpressionValidator控件,只要定义正确的表达规则就可以进行验证了。下面这段代码使用了RegularExpressionValidator控件,并设置了可以完成这种检查的属性。
用于报告漏洞的Web Service 这次移植还要增加报告漏洞的输入容量,并用Web Service来实现漏洞报告。为了有效的发布有关Visual Studio .NET和.NET框架的信息,Microsoft建立了许多包含了例子和信息的Web站点。这些站点需要一种机制,允许用户通过其它的Web站点报告漏洞,并将这些信息贮存在库中。站点还要求能实现离线报告漏洞,这样用户可以一次将许多漏洞发送到站点。要想实现这些目标,我们应该使用Web Service来完成报告漏洞的任务。 为了便于分类管理漏洞报告,而且能让合适的开发组看到报告,在一份漏洞报告中还需要提交许多其它数据(比如操作系统、语言、产品、地区等)。为了能让客户端应用程序提供丰富、有用的接口,有必要向客户端应用程序提供这些信息。为了能适用于更多的程序,开发组决定使用XML来传输数据。 为了简化报告漏洞服务的使用,开发组开发了多种接口,并实现了用多种方法保存报告。一个接口要求用户提供与漏洞报告数据有关的ID值,另一个接口允许客户端应用程序用字符串提交其它数据。如果采用后一种方式,漏洞报告服务将把字符串转变为相关的ID,并通过漏洞报告组件完成验证并保存。 原来的用Visual Basic 6.0开发的漏洞报告组件使用ADO与客户端程序进行数据交换。为了实现用XML传输数据,我们可以使用ADO记录的adPersistXML格式将记录中的数据转变为XML文档。最后还要将得到的XML漏洞报告转变为ADO记录,以便用Visual Basic 6.0的组件进行处理。 开发小组决定在Visual Basic .NET中重新编写报漏洞的类,这样可以充分利用ADO.NET中基于XML的dataset。这样做使得他们一方面可以方便地将数据以XML的形式提供给客户端的应用程序,同时,还可以使用Visual Basic .NET组件中简单易用的对象接口与数据进行交互。 一般说来,编写转换数据格式的代码是一种更为安全的选择。但考虑到我们迁移工程的主要目的是为了体验一下新的技术,采取这样的转换方法还是有一定的实际意义的。 移植站点的设计 在这一点上,开发组实现了开始这个项目时所定的目标。现存的客户站点被移植到了ASP .NET下,在这个过程中,还成功整合了.NET框架提供的新功能。另外,利用Visual Basic .NET开发出了一些新的功能模块,增强并扩展了这个站点的功能而并没有站点的大部分代码。图7说明了这个站点的体系结构是如何演变成现在的样子的。 ![]() 图7 新的体系结构 新的体系结构和Web站点增强了Visual Studio .NET和.NET框架开发组与测试站点间的联系。新的漏洞报告系统融入了现存的漏洞报告体系结构中,并能送到恰当的开发组手中。另外,移植站点为开发组提供了获得第一手资料的机会。 得到的教训 在迁移到Visual Studio .NET Beta的过程中,我们发现一些在Visual Basic 6.0和ASP中使用的开发技术,可以帮助你更容易的将程序实现移植到.NET。这种技术代表了良好编程风格,无论你是否移植到Visual Studio .NET,都能帮助你维护你的应用程序。 为了使你以后能更方便的实现迁移,请记住以下两点: 1. 不要依靠默认的对象属性。坚持在你的应用程序中显式地引用默认的属性。 2. 在调用方法时,应该在参数外加上圆括号。 ASP.NET和Visual Basic .NET可以和COM+组件实现通信的能力,使得移植应用程序成了一件简易完成的工作。这种互操作性可以使你大大的缩减在升级应用程序到.NET平台时所需修改的代码量。你可以以现有代码为基础,通过在Visual Basic .NET和ASP .NET中创建新的组件来实现对应用程序的迁移和功能扩充。 如果你想了解背景知识,请阅读: Visual Studio .NET站点 Microsoft .NET开发站点 ASP .NET应用程序 Jay Schmelzer是Clarity Consulting Inc.的合作伙伴。他负责检查设计、开发和实现大规模系统的开发小组的工作。他多次撰写了技术文档,并在会议上发言。 图3 Config.web文件
图4 认证代码
图5 客户端的验证逻辑
图6 在报告漏洞时选择产品的版本 ![]() > |