Node.js中调用WCF Web服务的实践

在Node.js环境中开发新的节点时,通常倾向于使用EST web services。同时,也经常需要在Node应用中调用现有的Web服务。当涉及到调用WCF Web服务时,由于WCF支持许多标准和协议,这可能会成为一个挑战,因为这些标准和协议在Node.js中并不直接支持。幸运的是,有wcf.js这个库可以帮助简化这个过程。

可能会问,为什么需要一个特殊的库来调用SOAP Web服务。毕竟HTTP在Node.js中是一等公民,可以直接通过HTTP发送SOAP到服务。然而,Web服务可能支持Ws-Security或MTOM等标准,而Node.js默认并不支持这些。这正是另一个项目ws.js所解决的问题。

既然有了ws.js,为什么还需要wcf.js呢?这两个项目是互补的。wcf.js并没有在ws.js的基础上增加新的标准实现,而是模仿了WCF的API。这意味着用户可以使用WCF的原生API来访问WCF,而不需要学习新的范式。所有这些都是用纯JavaScript实现的!

使用wcf.js

首先,需要安装wcf.js模块: npm install wcf.js

然后编写代码: var BasicHttpBinding = require('wcf.js').BasicHttpBinding; var Proxy = require('wcf.js').Proxy; var binding = new BasicHttpBinding({ SecurityMode: "TransportWithMessageCredential", MessageClientCredentialType: "UserName" }); var proxy = new Proxy(binding, "http://localhost:7171/Service/clearUsername"); var message = "" + "

" + "" + "" + "123" + "" + "" + ""; proxy.ClientCredentials.Username.Username = "yaron"; proxy.ClientCredentials.Username.Password = "1234"; proxy.send(message, "http://tempuri.org/IService/GetData", function(response, ctx) { console.log(response); });

如果觉得上面的代码很熟悉,那么是对的——它与WCF API相同。因此,可以自由地创建绑定和行为,就像在使用WCF一样。上面的示例在这一行初始化了一个wcf basicHttpBinding: binding = new BasicHttpBinding({ SecurityMode: "TransportWithMessageCredential", MessageClientCredentialType: "UserName" });

然后配置凭据: proxy.ClientCredentials.Username.Username = "yaron"; proxy.ClientCredentials.Username.Password = "1234"; 然后调用服务: proxy.send(message, "http://tempuri.org/IService/GetData", function(response, ctx) { ... }); 就像使用WCF一样!

自定义绑定示例

同样的方法可以帮助构建自定义绑定: var CustomBinding = require('wcf.js').CustomBinding; var MtomMessageEncodingBindingElement = require('wcf.js').MtomMessageEncodingBindingElement; var HttpTransportBindingElement = require('wcf.js').HttpTransportBindingElement; var Proxy = require('wcf.js').Proxy; var fs = require('fs'); var binding = new CustomBinding([ new MtomMessageEncodingBindingElement({ MessageVersion: "Soap12WSAddressing10" }), new HttpTransportBindingElement() ]); var proxy = new Proxy(binding, "http://localhost:7171/Service/mtom"); var message = '' + '' + '' + '' + '' + '' + '' + '' + '' + ''; proxy.addAttachment("//*[local-name(.)='File1']", "me.jpg"); proxy.send(message, "http://tempuri.org/IService/EchoFiles", function(response, ctx) { var file = proxy.getAttachment("//*[local-name(.)='File1']"); fs.writeFileSync("result.jpg", file); });

在这里需要注意的是自定义绑定上定义的通道: binding = new CustomBinding([...]); 可以创建自己的通道并将它们放入管道中。这个特定的例子使用了mtom通道。

为什么MTOM需要额外的工作?

上面的例子使用了MTOM通道。这就是为什么需要做一些额外的工作,通过指定base64元素路径: proxy.addAttachment("//*[local-name(.)='File1']", "me.jpg");

在WCF中不需要这样做,为什么Wcf.js需要这样做呢?让看看这个soap元素: 如果未使用MTOM,那么这部分将填充me.jpg的base64表示: PS2Kqw23A2A98... 需要告诉MTOM通道,将这个内容放到消息之外作为二进制有效载荷。那么为什么WCF不需要告诉它这个信息呢?WCF是一个完整的soap栈,它还根据WSDL生成代理。当WCF生成File1参数时,它将其标记为MTOM转换的候选。所以Wcf有这个信息来自Wsdl。由于Wcf.js是一个纯ws-*栈(而不是soap栈),它没有访问Wsdl,需要提供这个信息。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485