Web services having a greater interoperability to communicate messages across heterogeneous systems, however challenge is serializing the data into XML. Users may want to send images,videos, drawings, xml documents etc. together with SOAP message.
What is MTOM?
Message Transmission Optimization Mechanism (MTOM) is a mechanism of transferring transferring large amounts binary data as an attachment to SOAP message.
Typical SOAP message transmission shown in the below image
Image Source crosscheknet.com
WSE 3.0 supports Message Transmission Optimization Mechanism for transmitting large amounts of data to and from web services in earlier .NET FW versions now it is obsolete. We can write WCF service to use MTOM. In this post I am going to discuss uploading a file using WCF MTOM service and compares the payload of the message between text encoding and MTOM encoding.
1. Open the Visual Studio 2010 and create a WCF service
2. The service contract in the project looks as follows
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Runtime.Serialization;
5: using System.ServiceModel;
6: using System.ServiceModel.Web;
7: using System.Text;
8: using System.IO;
9:
10: namespace MTOMWcfService
11: {
12: //Service Contract UploadFile Service
13: [ServiceContract(Namespace="MTOMWcfService")]
14: public interface IService
15: {
16: [OperationContract]
17: byte[] UploadFile(Stream fileStream);
18: }
19: }
3. The service Implementation class as below. Upload File method saves the supplied stream disk.
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Runtime.Serialization;
5: using System.ServiceModel;
6: using System.ServiceModel.Web;
7: using System.Text;
8: using System.IO;
9:
10: namespace MTOMWcfService
11: {
12: public class MTOMService : IService
13: {
14:
15: public byte[] UploadFile(Stream fileStream)
16: {
17: IncomingWebRequestContext context =
WebOperationContext.Current.IncomingRequest;
18: int streamLength = (int)context.ContentLength;
19: byte[] fileData = new byte[streamLength + 1];
20: fileStream.Read(fileData, 0, streamLength);
21: using (Stream file = File.OpenWrite(@"G:\MTOMFile.jpg"))
22: {
23: CopyStream(fileStream, file);
24: }
25: fileStream.Close();
26: return fileData;
27: }
28:
29: public static void CopyStream(Stream input, Stream output)
30: {
31: byte[] buffer = new byte[8 * 1024];
32: int len;
33: while ((len = input.Read(buffer, 0, buffer.Length)) > 0)
34: {
35: output.Write(buffer, 0, len);
36: }
37: }
38: }
39:
40: }
4. The Web.Config file settings for this service as follows
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <system.serviceModel>
4: <protocolMapping>
5: <add scheme="http" binding="wsHttpBinding" />
6: </protocolMapping>
7: <bindings>
8: <wsHttpBinding>
9: <binding messageEncoding="Mtom"/>
10: </wsHttpBinding>
11: </bindings>
12: <!--For debugging purposes set
the includeExceptionDetailInFaults attribute to true-->
13: <behaviors>
14: <serviceBehaviors>
15: <behavior>
16: <serviceMetadata httpGetEnabled="True"/>
17: <serviceDebug includeExceptionDetailInFaults="False" />
18: </behavior>
19: </serviceBehaviors>
20: </behaviors>
21: </system.serviceModel>
22: </configuration>
Create service client object and call the uploadfile method in client project.
1: static void Main(string[] args)
2: {
3:
4: byte[] imageData = ReadFile(@"C:\Data\TestFile.jpg");
5: MemoryStream stream = new MemoryStream(imageData);
6: MTOMServiceClient.ServiceClient client = new
MTOMServiceClient.ServiceClient();
7:
8: byte[] data = client.UploadFile(stream);
9: Console.WriteLine(data.Length);
10: Console.WriteLine();
11: stream.Close();
12:
13: // Compare the wire representations of messages
with different payloads
14: CompareMessageSize(data.Length);
15:
16: Console.WriteLine();
17: Console.WriteLine("Press <ENTER> to terminate client.");
18: Console.ReadLine();
19:
20:
21: }
Above code reading a file from disk and uploading the stream to service method. We can also compare the payload size how it looks when we used the normal text encoding and MTOM encoding.
The CompareMessageSize method code look as below
1: static void CompareMessageSize(int dataSize)
2: {
3: // Create and buffer a message with a binary payload
4: byte[] binaryData = new byte[dataSize];
5:Message message = Message.CreateMessage(MessageVersion.Soap12WSAddressing10,
6: "action", binaryData);
7: MessageBuffer buffer = message.CreateBufferedCopy(int.MaxValue);
9: // Print the size of a text encoded copy
10: int size = SizeOfMtomMessage(buffer.CreateMessage());
11: Console.WriteLine("Text encoding with a {0} byte payload: {1}",
12: binaryData.Length, size);
14: // Print the size of an MTOM encoded copy
15: size = SizeOfMtomMessage(buffer.CreateMessage());
16: Console.WriteLine("MTOM encoding with a {0} byte payload: {1}",
17: binaryData.Length, size);
19: Console.WriteLine();
20: message.Close();
21: }
SizeOfMtomMessage method code below
1: static int SizeOfMtomMessage(Message message)
2: {
3: // Create an MTOM encoder
4: MessageEncodingBindingElement element = new
MtomMessageEncodingBindingElement();
5: MessageEncoderFactory factory = element.CreateMessageEncoderFactory();
6: MessageEncoder encoder = factory.Encoder;
7:
8: // Write the message and return its length
9: MemoryStream stream = new MemoryStream();
10: encoder.WriteMessage(message, stream);
11: int size = (int)stream.Length;
12:
13: stream.Close();
14: message.Close();
15: return size;
16: }
Read file method code follows
1: static byte[] ReadFile(string sPath)
2: {
3: //Initialize byte array with a null value initially.
4: byte[] data = null;//Use FileInfo object to get file size.
5: FileInfo fInfo = new FileInfo(sPath);
6: long numBytes = fInfo.Length;//Open FileStream to read file
7: //Use BinaryReader to read file stream into byte array.
8: FileStream fStream = new FileStream(sPath, FileMode.Open, FileAccess.Read);
9: //When you use BinaryReader, you need to supply
number of bytes to read from file.
10: //In this case we want to read entire file ,so supplying
total number of bytes.
11: BinaryReader br = new BinaryReader(fStream);
12: data = br.ReadBytes((int)numBytes);
13: return data;
14: }
The client application config looks as below
1: <configuration>
2: <system.serviceModel>
3: <bindings>
4: <wsHttpBinding>
5: <binding name="WSHttpBinding_IService" closeTimeout="00:010:00"
6: openTimeout="00:010:00" receiveTimeout="00:10:00" sendTimeout="00:010:00"
7: bypassProxyOnLocal="false" transactionFlow="false"
8: hostNameComparisonMode="StrongWildcard"
9: maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
10: messageEncoding="Mtom" textEncoding="utf-8" useDefaultWebProxy="true"
11: allowCookies="false">
12: <readerQuotas maxDepth="32" maxStringContentLength="8192"
13: maxArrayLength="16384"
14: maxBytesPerRead="4096" maxNameTableCharCount="16384" />
15: <reliableSession ordered="true" inactivityTimeout="00:10:00"
16: enabled="false" />
17: <security mode="Message">
18: <transport clientCredentialType="Windows" proxyCredentialType="None"
19: realm="" />
20: <message clientCredentialType="Windows" negotiateServiceCredential="true"
21: algorithmSuite="Default" />
22: </security>
23: </binding>
24: </wsHttpBinding>
25: </bindings>
26: <client>
27: <endpoint address="http://kalyan-pc/MTOMService/MTOMService.svc"
28: binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService"
29: contract="MTOMServiceClient.IService" name="WSHttpBinding_IService">
30: <identity>
31: <servicePrincipalName value="host/Kalyan-PC" />
32: </identity>
33: </endpoint>
34: </client>
35: </system.serviceModel>
36: </configuration>
You only see the considerable difference when you are sending the large binary files with SOAP message using MTOM. When you send the small files using MTOM you would not see any optimization in transfer.
The point is MTOM is able to transmit the binary data as raw message with SOAP by saving the time which results the smaller messages.
Share this post : |
[…] xml documents etc. together with SOAP message. What is MTOM? Message Transmission Optimization… Read more… Categories: .NET Web Service Share | Related […]
Do you know how to MTOM encode just a property of an object?
In your sample what if you had an object :
public class UploadData
{
public string FileName { get; set; }
public byte[] Content { get; set; }
}
and this object was inside another object let’s say:
public class RequestObject
{
public UploadData[] UploadFiles { get; set; }
}
and you wanted to upload the files using this object instead of a stream so your contract would look like:
[OperationContract]
ResponseObject UploadFile(RequestObject request);
Is it possible to serialize each Content as a separate part in the mtom encoded soap message?0
file1.xml
file2.xml
–MIMEBoundaryurn_uuid_FILE1
Content-Type: text/plain
Content-Transfer-Encoding: binary
Content-ID:
This is the content of doc 1
–MIMEBoundaryurn_uuid_FILE1–
–MIMEBoundaryurn_uuid_FILE2
Content-Type: text/plain
Content-Transfer-Encoding: binary
Content-ID:
This is doc 2
–MIMEBoundaryurn_uuid_FILE2–
What is about http://www.go4answers.com/Example/wcf-service-wont-accept-larger-files-36878.aspx
http://stackoverflow.com/questions/6690451/wcf-exists-and-partially-working-but-for-some-calls-returns-no-endpoint-listeni?noredirect=1#comment25684785_6690451