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.
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)))); } } }