NET 世界中的远程脚本

类别:.NET开发 点击:0 评论:0 推荐:
NET 世界中的远程脚本
Andrew Clinick
Microsoft Corporation
2001年11月12日

查看示例 service_vb.htm(英文)
查看示例 service_jscript.htm(英文)
查看 clsWeatherVB.asmx 的代码(英文)
查看 clsWeatherJScript.asmx 的代码(英文)

2000 年 3 月,我写了一篇文章,介绍 Microsoft® Remote Scripting(远程脚本)(英文)以及它是否可以用在 Web 服务领域。当时,我曾许诺向大家介绍如何利用已有的远程脚本知识,并将其移到 .NET Web 服务中。结果比我预想的要稍晚些,本文就要实现这一诺言了。今天,我们将专门讨论如何迁移远程脚本代码,使之成为 .NET Web 服务,同时还将针对 Microsoft® Visual Basic® .NET 和 Microsoft® JScript® .NET 这两种情况进行示范。代码的迁移涉及客户端和服务器两部分。我将以上篇文章中有关天气的远程脚本为例说明迁移过程,并把它迁移到 .NET 中。

为什么要用 Web 服务取代远程脚本?

WebService 行为同远程脚本相比有许多优点,尤其是在以下几个方面:

  1. 对服务器使用业界标准的 SOAP 请求。而远程脚本使用自己独有的 XML 变体作为响应。
  2. 与 ASP.NET 的配合非常好。远程脚本要求使用 ASP,这意味着它无法充分利用 ASP.NET 提供的所有增强,包括速度、编译语言和 .NET 框架。
  3. 服务器请求不局限于 HTTP GET。远程脚本在请求服务器时具有 2 KB 的数据限制。WebService 行为使用 HTTP POST,因此不会受到此限制的困扰。
  4. 可以通过浏览器使用 .NET 的功能。

迁移 VBScript 服务器代码

原示例代码使用 weatherservice.asp 来实现天气服务。其中包括一个 .vbs 源文件 (clsweather.vbs)。该文件实现了 clsWeather 类,并提供一些 Visual Basic Scripting Edition (VBScript) 代码用于创建该类的实例,然后在远程脚本上调用 RSDispatch 方法。这样,就可以调用该类的实例了。

<%@ LANGUAGE=VBSCRIPT %>
<script language="VBscript" runat="server" src="clsweather.vbs"></script>
<% 
set public_description = new clsWeather

' 调用 RSDispatch 以使用 public_description 对象并
将其方法提供给远程脚本调用
RSDispatch %>
<!--#INCLUDE FILE="../_scriptlibrary/rs.asp"-->

vbsweatherservice.asp

VBScript 类的实现非常简单,通过一个 getConditions 方法即可完成。该方法接受城市的名称,并返回其天气状况。由于这只是一个演示,所以仅适用于几个选定的城市。但是我想它与许多 Web 站点上的天气预报一样准确!

Class clsWeather
Public function getConditions(strCity)
   Select Case ucase(strCity)
      Case "伦敦"
         If month(now) <= 7 or month(now) >=9 then 
            getConditions = "阴"
         elseif month(now) = 8 then
            GetConditions = "局部地区阴"
         End if
      Case "西雅图"
         If (month(now) = 7) and (day(now) = 4) then
            GetConditions = "大雨"
         Else
            GetConditions = "雨"
         End if
      Case "路易斯安娜"
         GetConditions = "雾"
      Case "凤凰城"
         GetConditions = "炎热"
      Case Else
         GetConditions = "局部多云,间有阵雨"
   End select
end function
End Class

步骤 1:创建 Web 服务文件

.NET 框架为定义和实施 Web 服务提供了一种专门的文件类型:.asmx。迁移远程脚本 ASP 页,首先要做的就是创建一个 .asmx 文件。每个 .asmx 页都包含一个 WebService 指令,用于告知 ASP.NET 编写 Web 服务所用的语言,以及该实现所使用的类。WebService 指令上的 class 元素对应于原来的远程脚本 ASP 页中的 public_description 变量。

<%@ WebService Language="VB" Class="clsWeather" %>

步骤 2:添加现有的 VBScript

在 .asmx 文件中定义了 Web 服务之后,需要向该文件添加类的实现。由于原 ASP 页使用了 VBScript 类(几乎所有 VBScript 远程脚本文件都是这样),所以我直接将脚本复制并粘贴到 .asmx 页中。许多人都知道,VBScript 和 Visual Basic .NET 之间有许多地方不兼容,但幸运的是类的语法非常接近 (Class ... end class)。我原来的脚本非常简单,因此无需修改脚本的逻辑,即可在 Visual Basic .NET 中运行。但是,仍需要在代码中添加少许内容,使它能够进行编译,特别是要导入一些名称空间。

首先,要导入 Microsoft.VisualBasic 名称空间,确保能够在脚本代码中使用 Visual Basic 运行时所实现的函数(如 UCase)。导入 System 名称空间是大多数 .NET 应用程序的前提条件,因此为求方便,我直接添加了该代码。最后,由于要实现 Web 服务,因此该代码导入了 System.Web.Services

Imports Microsoft.VisualBasic
Imports System
Imports System.Web.Services

使脚本代码能够进行编译只是一个开始,要完成 Web 服务还有许多工作要做。ASP.NET 处理器要能够确定在 Web 服务上提供 clsWeather 类中的哪些方法。为此,需要在 Web 服务提供的每个方法中添加自定义属性 WebMethod。这比远程脚本机制更加灵活,因为后者可以通过远程脚本来调用远程脚本所提供的类中的每个公共方法。在 Visual Basic 中向方法添加自定义属性非常简单,只需要将它添加到方法的开始位置。因此,在本例中应该是:

<WebMethod()> Public function getConditions(strCity)

getConditions 方法的 VBScript 实现没有设置 strCity 参数的类型(这并不奇怪,因为 VBScript 不支持类型)。但这并不意味着 Web 服务就不能使用,我们可以认为它的类型是对象。不过,设置类型会使该函数更强壮,因为 Web 服务会在调用它时进行类型检查。为了利用类型检查机制,我将参数和函数的类型设置为字符串:

<WebMethod()> Public function getConditions(strCity as string) as string

步骤 3:保存并运行 .asmx 文件

现在我们可以将 .asmx 文件保存到服务器并进行测试。使用 ASP.NET 的 Web 服务的最大优点是每个 Web 服务都会创建一个自动测试 Web 页,这为检查代码提供了一种很好的测试工具。而使用远程脚本的客户除了要求支持 HTTP POST 以外,最常见的要求就是能有一种简单的方法来测试他们的代码。要访问该页,只需要在浏览器中输入 .asmx 文件的 URL。它将调出默认的测试页,并列出 Web 服务中可以使用的所有方法。

图 1:Web 服务测试页

单击 getConditions 链接调出一个页面,上面列出了该方法的所有参数。我们设置的类型此时开始发挥作用:ASP.NET Web 服务处理器将读取参数的类型信息,并为您提供一个简单的 html 窗体以便测试服务。

图 2:getConditions 的测试窗体

单击 Invoke(调用)按钮时,Internet Explorer 中会显示对 Web 服务的调用(由于是通过 HTTP GET 完成的,因此存在数据大小的限制)以及返回的 XML。

图 3:返回的 XML

迁移 JScript 版本

现有的 JScript 远程脚本的实现与 VBScript 版本非常类似,只是有一些 JScript 特有的内容。主要的不同在于:在 JScript .NET 之前,JScript 没有类的概念,因此原来的远程脚本 ASP 页有一个构造函数,该函数由 public_description 变量在页面上提供。

<%@ LANGUAGE=JSCRIPT %>
<script language="JScript" runat="server" src="clsweather.js"></script>
<% 
public_description = new clsWeather

' 调用 RSDispatch 以使用 public_description 对象
并将其方法提供给远程脚本调用
RSDispatch() %>
<!--#INCLUDE FILE="../_scriptlibrary/rs.asp"-->

jsweatherservice.asp

构造函数将 this.getConditions 设置为指向 getConditions 函数的指针,因此在创建新的 clsWeather 实例时,它会提供 getConditions 方法。getConditions 函数的实现与 VBScript 版本一样简单。

function clsWeather() {
   this.getConditions = GetCondition
function getCondition(strCity) {
   var now = new Date();
   switch (strCity.toUpperCase()) {
      case "伦敦":
         if (now.getMonth() <= 6||now.getMonth() >=8){
            return "阴"
         }
         if (now.getMonth() == 7) {
            return "局部地区阴"
         }
         break;
      case "西雅图":
         if (now.getMonth() == 6 && now.getDay()==4){
            return "大雨"
         }
         else {
            return "雨"
         }
         break;
      case "路易斯安娜":
         return "雾"
         break;
      case "凤凰城":
         return "热"
         break;
      default:
         return "局部多云,间有阵雨"
   }
}
}

步骤 1:创建 Web 服务文件

此步骤与 Visual Basic 几乎完全相同,只是语言的名称换成了 Jscript:

<%@ WebService Language="JScript" Class="clsWeather" %>

步骤 2:添加现有的 JScript

由于 Web 服务要在 JScript .NET 中运行,并将访问由 .NET 框架提供的 Web 服务功能,因此首先要向 .asmx 文件添加一组 import 语句,将所需的名称空间导入到代码中。JScript 使用 import 语句来指定名称空间,因此:

import System
import System.Web.Services

为了在 Web 服务中使用 JScript 代码,该代码必须位于 ASP.NET 处理器可以为其创建实例的某个类中。因为大部分代码都不需要更改,所以从构造函数迁移到类并不十分困难。只需将构造函数更改为类即可。

function clsWeather() {
   this.getConditions = getCondition
function getCondition(strCity) {
becomes:
class clsWeather {
   
function getConditions(strCity) {

在类 clsWeather 中自动创建函数 getCondition 作为公共函数,然后在读取文件顶部的 WebService 指令时将由 ASP .NET Web 服务处理器使用该函数。

现在,所有要做的事情就是用 WebMethod 属性将 getConditions 方法标记为 Web 方法。JScript 不需要在属性周围添加任何转义符,而只需要将属性放在行首。WebMethod 属性有一个 description 参数,该参数将成为用于所有 Web 服务调用的 Web 服务说明语言 (WSDL) 中的方法的 document 元素。其中的好处在于由 ASP.NET 提供的测试工具可以显示每个方法的说明。我在 JScript 示例中使用了 description 参数。

WebMethod(Description="返回城市的天气状况")
function getConditions(strCity) {

更改成类之后就可以运行 Web 服务了,但与 Visual Basic 示例一样,为 getConditions 函数的 strCity 参数设置类型会使该函数更强壮。在 JScript 中添加类型非常简单,只需要添加一个冒号,然后加上类型名称。

function getConditions(strCity : String) {

步骤 3:保存并运行 .asmx 文件

这一步与 Visual Basic 版本完全相同,在此不再赘述。

通过 Web 页使用 Web 服务

远程脚本的一个主要优点是:无需刷新 Web 页,就可以在客户端上调用服务器功能。现有的远程脚本客户端不能理解 Web 服务 XML,但这种优点并不会丢失,因为 WebService 行为与其非常相似,同时还提供了使用 HTTP POST 来调用服务器方法的突出功能。

远程脚本和 WebService 行为所共有的一项特性就是能够异步或同步调用方法。为自己的应用程序选择正确的机制是非常重要的,因为这对用户的体验有着显著的影响。调用 Web 服务可能需要一些时间,因此同步调用会锁住浏览器,这会令用户十分苦恼。这并不是说同步调用不好,而是强调应该在使用之前考虑一下其影响。

调用 getConditions 方法

2000 年 3 月的原示例中有一个简单的 Web 页。该页面接受文本框的值,调用 getConditions 方法,并用结果更新 Div。它先从远程脚本客户端 JScript 使用 RSGetASPObject 函数来获取 weatherservice.asp 页的客户端代理对象,再调用 getConditions 方法,然后再将 Div 的 innerHTML 设置为该方法的返回值。

svcWeather = RSGetASPObject("weatherservice.asp")
divWeather.innerHTML = svcWeather.getConditions(txtCity.value).return_value

这种方法的缺点在于它是同步的。换种方法,可以让页面使用 RSExecute 来处理要调用的方法的名称、参数以及当服务器的调用返回时要运行的函数的名称。

varTest = RSExecute("weatherservice.asp","getConditions",
 txtCity.value,getConditionsCallBack)

使用 WebService 行为可以获得非常相似的结果。要向您的 Web 页添加 WebService 行为,需要将该行为指定给页面上的某个元素。在本文附带的示例页面中,我添加了一个 div 并向它指定了该行为。该行为的实现形式是 HTML 组件 (.htc),因此可将它安装到您的 Web 服务器上。

<div id=service style="BEHAVIOR: url(webservice.htc)"></div>

WebService 行为中与 RSGetASPObject 对应的函数是 UseServiceUseService 可以创建一个客户端对象的实例,以便访问所提供的 Web 服务上的所有方法。例如,service.useService("clsWeather.asmx?WSDL","svcWeather") 将在服务对象上创建一个属性 svcWeather,并为其指定一个基于 clsWeather.asmx Web 服务的客户端对象。创建该对象后,远程方法的调用将通过以下方式完成:在返回的对象上调用 callService 方法,并使用回调函数的名称、Web 服务上的方法及其参数作为该方法的参数。当返回 getConditions 方法时,WebService 行为会调用 showWeather 函数,该函数把 innerHTML 设置为返回结果的值。

service.useService("clsWeather.asmx?WSDL","svcWeather")
   // 在 svcWeather Web 服务上调用 getConditions 方法
   iCallID = service.svcWeather.callService(showWeather,"getConditions",txtCity.value)
function showWeather(result)
{
       // 显示状况
        divWeather.innerHTML = result.value
}

总结

Web 服务的出现将会对我们的软件开发方式产生巨大的影响。我希望本文能够对您有所启发,使您能够轻松地迁移现有的远程脚本应用程序,以充分利用 Web 服务和 .NET 平台的功能。建议您进一步阅读 MSDN 上有关 WebService 行为(英文)的全部文档以及一些优秀的示例。与以往一样,我们非常感谢并鼓励您提供反馈意见,欢迎您与我们联系:[email protected]

本文地址:http://com.8s8s.com/it/it46189.htm