Parse/deserialize MTOM/XOP Data .NET
c#, deserialization, mtom, wcf, xml
Solution
You can deserialize the response using the WCF classes, as I'll show below. But before we proceed, this MTOM is invalid - the parameter `boundary` of the `Content-Type` header is malformed. Since it contains the '?' character, it needs to be quoted (look at the MIME RFC, section 5.1, definition of `token`).
Now, to deserialize it, you need to open the document with a MTOM reader - and `XmlDictionaryReader.CreateMtomReader` will give you exactly that. With that reader created, you can pass it to the `DataContractSerializer` to deserialize the object. The code below shows how this can be done.
public class StackOverflow_10531128
{
const string MTOM = @"MIME-Version: 1.0
Content-Type: Multipart/Related;boundary=DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM;
type=""application/xop+xml"";
start=""<DeltaSyncMTOMFetchResponse@mail.services.live.com>"";
--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM
content-transfer-encoding: binary
Content-Type: application/xop+xml; charset=utf-8; type=""application/xop+xml""
content-id: <DeltaSyncMTOMFetchResponse@mail.services.live.com>
<ItemOperations xmlns:xop=""http://www.w3.org/2004/08/xop/include"" xmlns:B=""HMMAIL:"" xmlns:D=""HMSYNC:"" xmlns=""ItemOperations:"">
<Status>1</Status>
<Responses>
<Fetch>
<ServerId>E631966A-9439-11E1-8E7B-00215AD9A7B8</ServerId>
<Status>1</Status>
<Message><xop:Include href=""cid:1.634715231374437235@example.org"" /></Message>
</Fetch>
</Responses>
</ItemOperations>
--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM
content-transfer-encoding: binary
Content-Type: application/octet-stream
content-id: <1.634715231374437235@example.org>
this is a binary content; it could be anything but for simplicity I'm using text
--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM--";
[DataContract(Name = "ItemOperations", Namespace = "ItemOperations:")]
public class ItemOperations
{
[DataMember(Order = 1)]
public int Status { get; set; }
[DataMember(Order = 2)]
public Responses Responses { get; set; }
}
[CollectionDataContract(Name = "Responses", Namespace = "ItemOperations:", ItemName = "Fetch")]
public class Responses : List<Fetch>
{
}
[DataContract(Name = "Fetch", Namespace = "ItemOperations:")]
public class Fetch
{
[DataMember(Order = 1)]
public Guid ServerId { get; set; }
[DataMember(Order = 2)]
public int Status { get; set; }
[DataMember(Order = 3)]
public byte[] Message { get; set; }
}
public static void Test()
{
MemoryStream ms;
ItemOperations obj;
DataContractSerializer dcs = new DataContractSerializer(typeof(ItemOperations));
string fixedMtom = MTOM.Replace(
"Multipart/Related;boundary=DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM;",
"Multipart/Related;boundary=\"DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM\";");
ms = new MemoryStream(Encoding.UTF8.GetBytes(fixedMtom));
XmlDictionaryReader reader = XmlDictionaryReader.CreateMtomReader(ms, Encoding.UTF8, XmlDictionaryReaderQuotas.Max);
obj = (ItemOperations)dcs.ReadObject(reader);
Console.WriteLine(obj.Status);
Console.WriteLine(obj.Responses.Count);
foreach (var resp in obj.Responses)
{
Console.WriteLine(" {0}", resp.ServerId);
Console.WriteLine(" {0}", resp.Status);
Console.WriteLine(" {0}", string.Join(" ", resp.Message.Select(b => string.Format("{0:X2}", (int)b))));
}
}
}
Problem
How can I parse/deserialize a MTOM/XOP response that I get from a web service using WCF? I have the response on disk. I have copied the response below: ``` Date: Wed, 02 May 2012 09:38:57 GMT Server: Microsoft-IIS/6.0 P3P:CP="BUS CUR CONo FIN IVDo ONL OUR PHY SAMo TELo" X-Powered-By: ASP.NET X-AspNet-Version: 4.0.30319 X-WindowsLive-Hydra: H: BLU165-ds6 V: 16.3.133.328 D: 2012-03-29T02:31:31 X-Response-Time: 78.1245 X-TransactionID: d491414e-46fd-47b2-82ce-e9cea9f564aa;BLU165-ds6;16.3.133.328;2012-05-02 09:38:57 UTC;78.1245 ms Set-Cookie: HMDST=dGVhcG90ZG9tZYtZm3GzLm1r3f+/q8+gdzrAPYmy9kJ+SmDZuFmVgk3E983xNyeoTZkkdIr6t8y3P4V+vPzmytdaqqFwtI8vBuc=; domain=.mail.services.live.com; path=/ Cache-Control: no-cache Pragma: no-cache Expires: -1 Content-Type: application/xop+xml Content-Length: 6386 MIME-Version: 1.0 Content-Type: Multipart/Related;boundary=DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM; type="application/xop+xml"; start="<DeltaSyncMTOMFetchResponse@mail.services.live.com>"; --DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM content-transfer-encoding: binary content-type: application/xop+xml; charset=utf-8; type="application/xop+xml" content-id: <DeltaSyncMTOMFetchResponse@mail.services.live.com> <ItemOperations xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:B="HMMAIL:" xmlns:D="HMSYNC:" xmlns="ItemOperations:"><Status>1</Status><Responses><Fetch><ServerId>E631966A-9439-11E1-8E7B-00215AD9A7B8</ServerId><Status>1</Status><Message><xop:Include href="cid:1.634715231374437235@example.org" /></Message></Fetch></Responses></ItemOperations> --DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM content-transfer-encoding: binary content-type: application/octet-stream content-id: <1.634715231374437235@example.org> ....Binary Content --DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM-- ``` Any help is much appreciated.