这个指南向你展示了如何从 Bindows™ 应用程序中非同步的调用一个 Web Service 。
Web Service 客户端的功能由 Microsoft Web Service Behavior 提供。BiWebService 类是个工厂类。这意味着创建一个新的 BiWebService 只需要创建一个带有行为的 HTML 元素。
var ws = new BiWebService(); alert(ws.tagName); // alerts "META"
这样做的优点是如果你知道如何使用 Microsoft Web Service Behavior,那么你就不需要再重新学习任何东西。缺点是命名约定和事件处理系统不同于这个对象,并且 Microsoft Web Service Behavior 的 API 的学习有点难度,另一个缺点是由于 Behaviors 的特性,它可能不会立即实现。因此初始化代码需要被一个特殊的行为生成事件调用。
为了使我们创建的应用程序更加清晰,所有 Web Service 的相关代码都被放置了应用程序的方法中。下面的方法创建了 Web service 对象并且调用了初始化和事件。
WebServiceTest.prototype.createWebService = function () { var oThis = this; this.webService = new BiWebService; // we need to wait until the web service is ready this.webService.onreadystatechange = function () { if ( this.readyState == "complete" ) { oThis.onReadyStateComplete(); } }; // called when the WSDL has been loaded this.webService.onserviceavailable = function () { oThis.onServiceAvailable(window.event); }; // hook up call back this.webService.onresult = function () { oThis.onResult(window.event.result); }; };
onReadyStateComplete, onServiceAvailable 和 onResult 的代码也可以写在 XML 文档里,但这样会使代码不清晰。 一旦 Web Service Behavior 已经就绪我们就需要告诉它在 Internet 上从哪里能找到 Web Service。
WebServiceTest.prototype.onReadyStateComplete = function () { this.statusSection.setText("Looking up WSDL"); // once complete we can initialize the service this.webService.useService(WebServiceTest.WSDL_URI, "MathService"); };
一旦 Web Service Description Language (WSDL) 文件被下载,Web Service 调用 onserviceavailable。接着调用 onServiceAvailable 方法,这个方法检验服务是否真的可用。
WebServiceTest.prototype.onServiceAvailable = function (e) { this._serviceAvailable = e.serviceAvailable; // once ready we can initialize the service if ( this.isWebServiceReady() ) this.statusSection.setText("Done"); else this.statusSection.setText("Failed to initialize web service"); };
onResult 中的代码稍候解释。
使用 callService 调用 Web Service。这是 MathService 服务的方法,我们把它加到上面的 onReadyStateComplete 方法。调用是非同步的,结果将会被传回通过调用 onResult 方法。
WebServiceTest.prototype.getResult = function () { // find the name of the function to call var sFunctionName; switch (this.operandButton.getText()) { case "+": sFunctionName = "add"; break; case "-": sFunctionName = "sub"; break; case "*": sFunctionName = "mul"; break; case "/": sFunctionName = "div"; break; } if ( this.isWebServiceReady() ) { this.statusSection.setText("Calling " + sFunctionName + "..."); // call the service using this name <strong>this.webService.MathService.callService(sFunctionName, Number(this.inputField1.getText()), Number(this.inputField2.getText()));</strong> } else { this.statusSection.setText("Web service is not ready"); alert("Web service is not ready"); } };
一旦通过 onResult 方法获取了结果。我们就要监测错误,如果没有错误我们就改变结果的文本域使之从服务器显示结果值。
WebServiceTest.prototype.onResult = function (oResult) { if (oResult.error) { this.statusSection.setText("Done but with errors"); alert("Got an error\n\n" + oResult.errorDetail.string); } else { // bug in MS Behavior HTC that does not correctly map Infinity // this is not usually an issue but for this little app it is nifty // to correctly support this if (oResult.value == "INF") oResult.value = Infinity; this.resultField.setText(oResult.value); this.statusSection.setText("Done"); } };
剩下的事情就只有 GUI 组件了。如果感兴趣你可以查看 XML 源文件。
默认情况下 IE 不允许来自其它域的 Web Service 工作。这个要通过修改 IE 设置来改变这种状况 工具 / Internet 选项... / 安全 / 自定义级别 / 其它 / 通过域访问数据资源 ,改为 提示 或 启用。另一种可用的方法是创建一个在 Web 服务器上建立代理服务器以转发 Web Service 请求。