2012-05-10 69 views
6

¿Cómo puedo analizar/deserializar una respuesta MTOM/XOP que obtengo de un servicio web utilizando WCF? Tengo la respuesta en el disco. He copiado la respuesta a continuación:Parse/deserialize MTOM/XOP Data .NET

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-- 

Cualquier ayuda es muy apreciada.

+3

re: 'Debe haber una clase/método que haga lo que estoy intentando?' ¿No sería agradable? Lamentablemente, MS dice que no hacen archivos adjuntos en su implementación de MTOM. No hay un método definido para acceder al 'cid' o su contenido. Estoy trabajando en una clase de extensión que puede manejar esto (subvirtiendo el canal y analizando el MTOM de retorno a mano). Te avisaré si encuentro algo ** funcional **. pero no contengas la respiración ** elegante **. –

+0

¡Nunca aguantará la respiración tanto tiempo! –

+0

@ user349026 - Es posible que tenga que esperar un poco más. :(Resulta que lo que implementé es propiedad de la compañía (según los abogados). Tendré que reinventarlo en mi propio tiempo y en las computadoras, de manera suficientemente diferente a la original para poder publicarlo aquí. –

Respuesta

4

Puede deserializar la respuesta utilizando las clases de WCF, como mostraré a continuación. Pero antes de continuar, este MTOM no es válido: el parámetro boundary del encabezado Content-Type está mal formado. Como contiene el '?' carácter, necesita ser citado (consulte MIME RFC, sección 5.1, definición de token).

Ahora, para deserializarlo, debe abrir el documento con un lector MTOM, y XmlDictionaryReader.CreateMtomReader le dará exactamente eso. Con ese lector creado, puede pasarlo al DataContractSerializer para deserializar el objeto. El siguiente código muestra cómo se puede hacer esto.

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)))); 
      } 
     } 
    } 
+0

si el MTOM tiene una secuencia binaria de una imagen, y se convierte en una cadena como en su ejemplo, ¿dañaría o no la secuencia? – Victor

+0

Este es un ejemplo simple que muestra cómo leer el documento MTOM utilizando las clases WCF, y para completarlo y autocontenido codifiqué el MTOM "documento" como una cadena en el archivo. Lo que normalmente sucedería es que el documento se leería desde una fuente externa (archivo, red, etc.) y los bytes se codificarían correctamente. (y sería leído correctamente por el lector MTOM). – carlosfigueira