Category Archives: SOA and Interop

WCF is the now ‘standard’ (for .NET) Object Oriented Web Services API. This post was originally about the now legacy WSE technology but is still interesting by the description of MTOM (still relevant in WCF or without).

If using WCF here are the ‘out of the box’ bindings:

Table 1: WCF standard bindings

Name Transport Encoding Interop
BasicHttpBinding HTTP/HTTPS Text +
NetTcpBinding TCP Binary -
NetPeerTcpBinding P2P Binary -
NetNamedPipeBinding IPC Binary -
WSHttpBinding HTTP/HTTPS Text,MTOM +
WSFederationBinding HTTP/HTTPS Text,MTOM +
WSDualHttpBinding HTTP Text,MTOM +
NetMsmqBinding MSMQ Binary -
MsmqIntegrationBinding MSMQ Binary +

 

 

Choosing MSMQ for a transport protocol mandates WCF to WCF or WCF to MSQM communication, but it provides for disconnected offline work. 

—————————————————

1/13/2006

MTOM is a major reason to use WSE 3.0. In fact I cannot think of a good reason to be writing Web Services in VS 2005 without WSE 3.0.

What is MTOM? It is well said in the article: “What’s New in Web Services Enhancements 3.0″

Sending Large Amounts of Data with MTOM

MTOM, otherwise known as Message Transmission Optimization Mechanism, enables you to send binary data efficiently as part of a SOAP message. The key word here is optimization, since to all intents and purpose this is transparent to the developer and simply just happens when enabled. MTOM is a W3C recommendation that replaces DIME and WS-Attachments as the mechanism for sending large amounts of data such as document files and images.

There are three key benefits to using MTOM over the existing technologies.

  • Security. The primary benefit is that MTOM composes with security (via WS-Security), meaning that the data is secure as well as the SOAP message. With DIME the attachments are not secure (unless you used transport-level security) and by simply using any TCP trace utility or a network protocol analyzer, you could see the attached data in plain text.
     
  • Reduced Wire Size. With MTOM, binary character values are sent on the wire as a MIME attachment and these are referenced from the body of the SOAP message. Typically, due to specific character ranges allowed in XML 1.0 (for example, most characters http://en.wikipedia.org/wiki/Base64). The resultant base64-encoded data has a length that is approximately 33% greater than the original binary data. MTOM is simply another encoding algorithm that does not suffer from this size expansion and so the wire size is smaller. Wire size is only an issue where bandwidth is a significant enough restriction that it affects the messages.Note Although MTOM reduces wire size when composed with security, it does not reduce the processing time either on the client or the server in order to secure the message. This is because WS-Security requires the data to be converted to base64 to apply normalization and canonicalization algorithms and hence generate the cipher values in order to achieve interoperability.
     
  • Simplified Programming Model. With MTOM you do not have to use a separate attachments collection as with DIME in order to send the data. All you do is write the service and then simply indicate that this service supports MTOM encoding in the application’s configuration file. Any byte[] types returned from the service are then MTOM-automatically encoded.Having discussed the benefits of MTOM, let’s take a look at a simple Web service that returns binary files from a server to a client. The code below shows the service that returns that file as a GetFileResponse type for a given file name. This code is taken from the BinaryDataMTOM QuickStart sample shipped with the WSE 3.0 samples.

[WebService(Namespace = http://stockservice.contoso.com/wse/samples/2005/10)]

public class BinaryDataMTOMService : System.Web.Services.WebService
{
//This WebMethod returns MTOM encoded binary data
[WebMethod]
public GetFileResponse GetFile(string fileName)
  {
          GetFileResponse response = new GetFileResponse();
          response.FileName = fileName;

          String filePath = AppDomain.CurrentDomain.BaseDirectory +
          @”App_Data\” + fileName;
          response.FileContents = File.ReadAllBytes(filePath);
          return response;
  }

}
// Web Method return type
[XmlRoot("getFileResponse",
Namespace = "http://stockservice.contoso.com/wse/samples/2005/10")]
public class GetFileResponse
{
[XmlElement("fileName", IsNullable = false)]
public string FileName;
[XmlElement("fileData", IsNullable = false)]
public byte[] FileContents;
}

The GetFileResponse type is where the MTOM magic is applied, since the FileContents is returned as a byte[], achieved by simply reading the file using the File.ReadAllBytes method. MTOM is turned on in configuration, either on the client or the server, via the Messaging tab in the WSE Configuration Tool. Figure 6 shows these MTOM configuration options which, when set, are either written to the client’s app.config or the server’s web.config files.

 

There are three server MTOM modes: “optional”, “always”, and “never”.

‘Always’ means that the service “always” requires MTOM messages from the client and will “always” return response messages using MTOM.

Never means that MTOM will never be used—and the service will reject MTOM requests.
Optional (the default) means the service will respond in kind to the type of message sent by the client. So if the client sends an MTOM request, it will respond with an MTOM response.
On the client MTOM is either “On” or “Off” (the default).
Let’s now look at the client-side code to call this MTOM-enabled service, which returns the GetFileResponse type and then writes the file to disk. Notice that this is no different from calling a ASP.NET Web service in order to return a file, it just happens to optimize the transmission using MTOM. //Get winter.jpg file as a binary file

——————————————–

// MTOM is enabled by default for the client in app.config via
// the element

String fileName = “Winter.jpg”;

BinaryDataMTOMServiceWse serviceproxy = new BinaryDataMTOMServiceWse();

localhost.GetFileResponse response = serviceproxy.GetFile(fileName);

Console.WriteLine(“File Name: {0}”, response.fileName);

Console.WriteLine(“Unsecured Bytes Received (at Client): {0}”, response.fileData.Length);

File.WriteAllBytes(response.fileName, response.fileData);

——————————————–

You can choose to override the MTOM configuration setting for each client proxy by calling the RequireMtom method on the WSE-generated proxy. For example, the following code turns off MTOM for the proxy

serviceproxy.RequireMtom = false;

So, given all this magic that happens under the covers, how do you know that binary data is being sent on the wire? In order to see this we need to use a TCP trace tool such as TcpTrace.exe, which can be downloaded at http://www.pocketsoap.com/tcptrace/.

If you run this utility (remembering to add port 8080 to the URL either in the client’s app.config file or in the client proxy-generated code in the reference.cs file to ensure that the request message goes via the TcpTrace.exe utility).

Streaming binary data with MTOM

This previous code example using MTOM caches the file on the server by first loading it into the FileContents byte[] on the server. For large files with many requests this would take up a large amount of memory on the server. What you want to be able to do is stream the file over the network stream from the server to the client. For ASP.NET Web services hosted in IIS using HTTP this is possible by implementing a return type derived from IXmlSerializable.

If you take another look at the code in the BinaryDataMTOMService.cs file in the BinaryDataMTOM QuickStart sample, you will find another Web service that instead returns a type called GetFileResponseWrapper that is derived from IXmlSerializable. This Web service performs the same function of returning a named file, but this time, by implementing the ReadXml and WriteXml methods on the IXmlSerializable interface, the file is streamed from the server to the network.