Click here to Skip to main content
Click here to Skip to main content

Wcf.js: Call WCF web services from Node.js

By , 8 May 2012
Rate this:
Please Sign up or sign in to vote.

Introduction

Node.js is becoming a great choice for developers in start ups and enterprises. While REST web services are the preferred choice for new node development, there is also a need to call existing web services from within Node apps. When calling WCF web services this is a challenge since WCF supports a lot of standards and protocols which are not easy to generate. Wcf.js is a library for node.js that aims to simplify this scenario. 

Background 

The first question that you may be asking is why do we need a special library at all for calling SOAP web services. After all HTTP is a first class citizen in node.js and we can simply send the SOAP over HTTP to the service. However web services may support standards like Ws-Security or MTOM which node does not support out of the box. Actually this is exactly what another project, ws.js, solves. 

So if we have ws.js why do we also need wcf.js?

The two projects are complementing each other. While wcf.js does not add any new standards implementations on top of ws.js, it mimics the WCF API. This means users can access WCF using its native API and do not need to learn a new paradigm. And all this is done in a pure JavaScript way! 

Using the code 

1. First you must install the Wcf.js module:

npm install wcf.js

2. Now write your code: 

var BasicHttpBinding = require('wcf.js').BasicHttpBinding
  , Proxy = require('wcf.js').Proxy
  , binding = new BasicHttpBinding(
        { SecurityMode: "TransportWithMessageCredential"
        , MessageClientCredentialType: "UserName"
        })
  , proxy = new Proxy(binding, "http://localhost:7171/Service/clearUsername")
  , message =  "<Envelope xmlns='http://schemas.xmlsoap.org/soap/envelope/'>" +
                 "<Header />" +
                   "<Body>" +
                     "<GetData xmlns='http://tempuri.org/'>" +
                       "<value>123</value>" +
                     "</GetData>" +
                    "</Body>" +
               "</Envelope>"
proxy.ClientCredentials.Username.Username = "yaron"
proxy.ClientCredentials.Username.Password = "1234"
proxy.send(message, "http://tempuri.org/IService/GetData", function(response, ctx) {
  console.log(response)
});     

If this code looks familiar then you are right - it is the same as the WCF API. So you can freely create bindings and behaviors the same way you would do that with WCF. The above example initializes a wcf basicHttpBinding in this line: 

binding = new BasicHttpBinding(
        { SecurityMode: "TransportWithMessageCredential"
        , MessageClientCredentialType: "UserName"
        }) 

Then it configures credentails:

proxy.ClientCredentials.Username.Username = "yaron"
proxy.ClientCredentials.Username.Password = "1234" 

and then calls the service:

proxy.send(message, "http://tempuri.org/IService/GetData", function(response, ctx) {
  ...
});       

Exactly as with WCF! 

Custom binding sample  

The same approach can help us build a custom binding: 

var CustomBinding = require('wcf.js').CustomBinding
  , MtomMessageEncodingBindingElement = require('wcf.js').MtomMessageEncodingBindingElement
  , HttpTransportBindingElement = require('wcf.js').HttpTransportBindingElement
  , Proxy = require('wcf.js').Proxy
  , fs = require('fs')
  , binding = new CustomBinding(
        [ new MtomMessageEncodingBindingElement({MessageVersion: "Soap12WSAddressing10"}),
        , new HttpTransportBindingElement()
        ])
  , proxy = new Proxy(binding, "http://localhost:7171/Service/mtom")
  , message = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">' +
                '<s:Header />' +
                  '<s:Body>' +
                    '<EchoFiles xmlns="http://tempuri.org/">' +
                      '<value xmlns:a="http://schemas.datacontract.org/2004/07/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">' +
                        '<a:File1 />' +                   
                      '</value>' +
                    '</EchoFiles>' +
                  '</s:Body>' +
              '</s:Envelope>'
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)    
}); 

What you should note here is how channels are defined on the custom binding:

  binding = new CustomBinding(
        [ new MtomMessageEncodingBindingElement({MessageVersion: "Soap12WSAddressing10"}),
        , new HttpTransportBindingElement()
        ])  

You can create your own channels and put them in the pipeline. This specific example uses the mtom channel.  

Why MTOM requires extra work?  

The above example uses the MTOM channel. This is why we are required to do some more work by specifying the base64 element path: 

proxy.addAttachment("//*[local-name(.)='File1']", "me.jpg"); 

We are not required to do this in WCF so why does Wcf.js requires this?

Let's take a look at this soap element: 

<a:File1 />  

If MTOM was not used then this section was filled with the base64 representation of me.jpg:

 <a:File1>PS2Kqw23A2A98...</a:File1> 

We need to tell the MTOM channel to take this content and put it outside the message as a binary payload. So why WCF does not require us to tell it this information? WCF is a full soap stack which also generates proxies based on WSDL. When WCF generated the File1 parameter it marked it as a candidate for MTOM transformation. So Wcf has this information from the Wsdl. Since Wcf.js is a pure ws-* stack (and not soap stack), it does not have access to the wsdl and we need to supply this information. 

Supported Bindings 

Wcf.js currently supports a subset of:

  • BasicHttpBinding
  • WSHttpBinding
  • CustomBinding

The current subset includes:

  • MTOM / Text encodings
  • WS-Addressing (all versions)
  • Transport Security (SSL)
  • Transport with message credential (Username)  

The future of Ws.js     

Wcf.js is a pure JavaScript implementation of WCF for Node.js.   

Wcf.js is a growing framework. For future versions I plan to add more binding support like net.tcp and proprietary security negotiations in WsHttpBinding. If you have any special request send me an email from my blog. If you want to help feel free to fork Wcf.js on github - that's the fastest way to grow Wcf.js.  

More information 

Check out the project github page 

Check out my blog 

Check out my twitter 

Drop me an email from my blog  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Yaron Naveh
Software Developer (Senior)
Israel Israel
Web services interoperability expert.
 
http://webservices20.blogspot.com/
Follow on   Twitter

Comments and Discussions

 
QuestionIssue faced while consuming WCF webservice using wcf.js module using node.js Pinmemberamjad syed19-Jul-12 3:28 
AnswerRe: Issue faced while consuming WCF webservice using wcf.js module using node.js PinmemberYaron Naveh19-Jul-12 13:36 
Hi Syed
 
You should not use Wcf.js for REST web services. It only works with soap services, and is recommended when ws-* settings are used. Please send me your wcf service config file (for the non-rest service). send it via mail since xml is not displayed here well.
QuestionVote of 5 PinmemberGanesanSenthilvel8-May-12 10:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140415.2 | Last Updated 8 May 2012
Article Copyright 2012 by Yaron Naveh
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid