Using MTOM with WCF
Suppose you want to transmit large binary contents (a file, for example) through WCF. In the usual way, you would use a classe decorated with a [DataContract] attribute, and you would have inside of it a property of type Byte[], marked with a [DataMember], where the actual contents would be placed. There is a problem with this solution, however: being SOAP based exclusively in text (it is just XML), if you want to send special characters inside of it, you must convert them into text, using common encoding techniques such as Basw 64. Now, WCF does this for you, you just have to supply the byte array, and it does all the work, the problem is that Base 64 typically increases the total size by 33%.
The good news is that the good guys at W3C have developed a standard, named MTOM - Message Transmission Optimization Mechanism - that allows you to send binary content over the wire as is, that is, without translation to text. You can read about it here. I will not go into details, in order to use MTOM, you must do the folowing:
-
The method that is sending MTOM content can only receive or return classes that have the [MessageContract] attribute, not [DataContract], or "primitive" types;
-
All the byte array properties must have a [MessageBodyMember] attribute, not [DataMember] nor [MessageHeader], and all the other properties must have a [MessageHeader] attribute;
-
Instead of Byte[] you can also pass a Stream object, the results are the same;
-
All eventual classes that the parameter or return classes derive from must also have the [MessageContract] attribute;
-
In the <binding> elements for you service (both client and server), you must set the messageEncoding attribute to Mtom.
And that's it! You will notice a significant throughput increase, specially for large contents.
See this example:
[
MessageContract]public
class FileResponse{
[MessageHeader] public String Filename { get; set; } [MessageBodyMember] public Byte[] Contents { get; set; }}
[
ServiceContract]public
interface IFileService{
[OperationContract] FileResponse GetFile(String filename);}
/* client and server */
<bindings><
wsHttpBinding> <binding name="WsHttpMtomBinding" messageEncoding="Mtom" /></wsHttpBinding>
</bindings>
/* server only */
<
services> <service behaviorConfiguration="Behavior" name="FileService"><
endpoint binding="wsHttpBinding" bindingConfiguration="WsHttpMtomBinding" contract="IFileService"></service>
</services>
/* client only */
<
client><
endpoint address="http://localhost:8001/FileService.svc" binding="wsHttpBinding" bindingConfiguration="WsHttpMtomBinding" contract="IFileService" name="IFileService"/></client>