Wednesday, December 18, 2013

Consuming EBS-EDT SOAP service from WCF

@YaronNaveh

If you want personal guidance with EBS-EDT feel free to mail me at yaronn01@gmail.com

A while ago the Ontario Ministry of Health and Long-Term Care published this document, which explains how to consume their new SOAP web service. (In favor of Google the exact title is "Technical Specification for Medical Claims Electronic Data Transfer (MCEDT) Service via Electronic Business Services (EBS) Ministry of Health and Long-Term Care"). I have received over a dozen of questions about how to consume this service with WCF. Unfortunately it is not a simple task since the service uses a complex configuration which is not available in any of the built-in WCF bindings. However it is possible to do it with some custom code. Bellow I describe the general scheme for this to work. I know some community members are preparing a simple wrapper for this so I will publish it here once ready.


The Errors
Depending on which path you chose for implementation, the most common error message you are likely to receive is the dreadful:

The incoming message was signed with a token which was different from what used to encrypt the body. This was not expected.

There are other possible errors as well or some consumers may not know where to start.

The Solution
1. Since the client needs to send both username token and an X.509 certificate (and sign with the latter) we need to write a code binding:


One thing you want to notice in this code is that it contains the username and password, so change them according to your credentails.
Another thing to notice is that the client certificate is loaded from disk. You could change that to the windows certificate store if you wish. As for the server certificate, you could put any dummy certificate there, including the same one as the client certificate (it will not be used but WCF needs something in this setting).
Also note the EnableUnsecuredResponse=true. It is a key for the next steps.

2. Since the request needs to be signed only (not encrypted) let's configure the contract in reference.cs with the ProtectionLevel attribute:


3. WCF is reluctant to decrypt the response. For this reason we need to do the decryption manually. This is the hardest part but I give most of the code here so hopefully it will be easier. You need to implement a custom message encoder and configure the binding above to use your encoder instead of text message encoder. Read here on how to implement an encoder.

4. You need to override the ReadMessage method of the encoder and decrypt the response message in it.

This code shows how to decrypt a message (not necessarily in the context of an encoder):


This code needs access to your private key so it could extract the session key in the message and it also needs some elements from the response. Once you get the decypted message you can replace the encypted body part in the message provided by the encoder with the decrypted message.

5. The last mission to accomplish in the encoder is to delete the <security> element (and all of its child nodes) from the response message before you return it to WCF. Otherwise WCF will try to decrypt the message which is redundant since we just unencrypted it now (WCF decryption would fail anyway). Remember the EnableUnsecuredResponse flag from step #2? It tells WCF not to expect any security, so stripping the elements out is safe.

Information on some possible errors in this process is available here.

MIME Attachments

Hopefully by now you have a working client. Some of the operations also receive an attachment from the service. This attachment in SwA (Soap with Attachments) which is a MIME format a little different than the MTOM whcih WCF knows about.To extract this attachment you could use some kind of a mime parser library as the first step of your encoder (apply it over the raw bytes from the network). Copy the first MIME part to the Message object (this is the SOAP). The second part will be the attachment which you can keep on the custom encoder as a property or on some other context available to your application code.

Fault Contract
Since there is no formal fault contract in the WSDL you should inspect any incoming soap fault using a custom message inspector.

To sum up, consuming EBS-EDT from WCF is not easy but doable, good luck!

@YaronNaveh

What's next? get this blog rss updates or register for mail updates!