Анализ/десериализация данных MTOM/XOP .NET

Как я могу разобрать/десериализовать MTOM/XOP ответ, который я получаю от веб-службы, использующей WCF? У меня есть ответ на диске. Я скопировал ответ ниже:

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="<[email protected]>";

--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM
content-transfer-encoding: binary
content-type: application/xop+xml; charset=utf-8; type="application/xop+xml"
content-id: <[email protected]>

<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:[email protected]" /></Message></Fetch></Responses></ItemOperations>
--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM
content-transfer-encoding: binary
content-type: application/octet-stream
content-id: <[email protected]>

....Binary Content
--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM--

Буду признателен за любую оказанную помощь.


person Community    schedule 10.05.2012    source источник
comment
re: There must be a class/method that does what I am trying? Было бы неплохо. К сожалению, MS говорит, что они не делают вложения в своей реализации MTOM. Не существует определенного метода доступа к cid или его содержимому. Я работаю над классом расширения, который может справиться с этим (подрывая канал и анализируя возвращаемый MTOM вручную). Я дам вам знать, если придумаю что-нибудь функциональное. но не задерживайте дыхание на элегантном.   -  person Jesse Chisholm    schedule 17.06.2012
comment
Никогда не задержу дыхание так долго!   -  person    schedule 05.03.2013
comment
@ user349026 - Возможно, вам придется подержать его немного дольше. :( Оказывается, то, что я реализовал, является собственностью компании (по словам юристов). Мне придется заново изобретать это в свободное время и на компьютерах, достаточно отличающееся от моего оригинала, чтобы я мог опубликовать это здесь.   -  person Jesse Chisholm    schedule 16.12.2014


Ответы (1)


Вы можете десериализовать ответ, используя классы WCF, как я покажу ниже. Но прежде чем мы продолжим, этот MTOM недействителен — параметр boundary заголовка Content-Type имеет неверный формат. Так как он содержит '?' символ, его необходимо заключить в кавычки (см. MIME RFC, раздел 5.1, определение token).

Теперь, чтобы его десериализовать, вам нужно открыть документ с помощью MTOM-ридера — и XmlDictionaryReader.CreateMtomReader даст вам именно это. Создав этот считыватель, вы можете передать его DataContractSerializer для десериализации объекта. Код ниже показывает, как это можно сделать.

    public class StackOverflow_10531128
    {
        const string MTOM = @"MIME-Version: 1.0
Content-Type: Multipart/Related;boundary=DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM;
    type=""application/xop+xml"";
    start=""<[email protected]>"";

--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM
content-transfer-encoding: binary
Content-Type: application/xop+xml; charset=utf-8; type=""application/xop+xml""
content-id: <[email protected]>

<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:[email protected]"" /></Message>
        </Fetch>
    </Responses>
</ItemOperations>
--DeltaSync91ABCB4AF5D24B8F988B77ED7A19733D?MTOM
content-transfer-encoding: binary
Content-Type: application/octet-stream
content-id: <[email protected]>

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))));
            }
        }
    }
person carlosfigueira    schedule 07.04.2013
comment
если в MTOM есть двоичный поток изображения, и он преобразуется в строку, как в вашем примере, повредит ли это поток или нет? - person Victor; 16.07.2013
comment
Это простой пример, показывающий, как читать документ MTOM с помощью классов WCF, и чтобы сделать его полным и автономным, я жестко запрограммировал документ MTOM в виде строки в файле. Что обычно происходит, так это то, что документ будет прочитан из какого-то внешнего источника (файла, сети и т. д.), и байты будут правильно закодированы (и будут правильно прочитаны считывателем MTOM). - person carlosfigueira; 17.07.2013
comment
Как я могу сделать то же самое в ядре С#? - person Piero Alberto; 13.03.2018