2008-08-16 11 views
9

Es 2008, y todavía estoy desgarrado por este. Así que estoy desarrollando un método web que necesita un tipo complejo pasado y devuelto. Las dos opciones que estoy jugando con son:¿Cuál es su método preferido para enviar datos complejos a través de un servicio web?

  1. pasar y devolver objetos de negocios reales con los datos y el comportamiento. Cuando se ejecuta wsdl.exe, creará automáticamente clases de proxy que contengan solo la porción de datos, y estos se convertirán automáticamente desde y hacia mis objetos comerciales reales en el lado del servidor. En el lado del cliente, solo podrán usar el tipo de proxy tonto, y deberán mapearlos en algunos objetos comerciales reales como mejor les parezca. Un gran inconveniente aquí es que si "poseo" tanto el lado del servidor como el del cliente, y quiero usar el mismo conjunto de objetos comerciales reales, puedo encontrarme con ciertos dolores de cabeza con conflictos de nombres, etc. (Dado que los objetos reales y el los proxies se nombran igual.)

  2. Olvídese de intentar pasar objetos comerciales "reales". En su lugar, solo cree objetos simples DataTransfer que correlacionaré de ida y vuelta a mis objetos comerciales reales manualmente. De todos modos, wsdl.exe todavía los copia a objetos proxy nuevos, pero al menos no me estoy engañando a mí mismo al pensar que los servicios web pueden manejar de forma nativa los objetos con la lógica comercial en ellos.

Por cierto - ¿Alguien sabe cómo decirle a wsdl.exe no crea una copia del objeto? ¿No deberíamos poder decirlo, "Oye, usa este tipo existente aquí mismo. No lo copies!"

De todos modos, por el momento me he conformado con el # 2, pero tengo curiosidad por lo que piensan. Tengo la sensación de que hay manera mejores maneras de hacer esto en general, y puede que ni siquiera sea totalmente exacto en todos mis puntos, así que por favor déjenme saber cuáles han sido sus experiencias.

Actualización: Acabo de descubrir que VS 2008 tiene una opción para reutilizar los tipos existentes al agregar una "Referencia de servicio", en lugar de crear un nuevo tipo idéntico en el archivo proxy. Dulce.

Respuesta

1

También hay un argumento para separar los niveles: tener un conjunto de objetos serializables que pasar al y desde el servicio web y un traductor para mapear y convertir entre ese conjunto y los objetos comerciales (que pueden tener propiedades no adecuadas para pasar por el cable)

Es el enfoque preferido por la fábrica de software del servicio web service factory y significa que puede cambiar sus objetos comerciales sin romper la interfaz/contrato del servicio web

4

Haría un híbrido. Me gustaría utilizar un objeto como éste

public class TransferObject 
{ 
    public string Type { get; set; } 
    public byte[] Data { get; set; } 
} 

entonces tengo una pequeña utilidad agradable que serializa un objeto y luego lo comprime.

public static class CompressedSerializer 
{ 
    /// <summary> 
    /// Decompresses the specified compressed data. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="compressedData">The compressed data.</param> 
    /// <returns></returns> 
    public static T Decompress<T>(byte[] compressedData) where T : class 
    { 
     T result = null; 
     using (MemoryStream memory = new MemoryStream()) 
     { 
      memory.Write(compressedData, 0, compressedData.Length); 
      memory.Position = 0L; 

      using (GZipStream zip= new GZipStream(memory, CompressionMode.Decompress, true)) 
      { 
       zip.Flush(); 
       var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
       result = formatter.Deserialize(zip) as T; 
      } 
     } 

     return result; 
    } 

    /// <summary> 
    /// Compresses the specified data. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="data">The data.</param> 
    /// <returns></returns> 
    public static byte[] Compress<T>(T data) 
    { 
     byte[] result = null; 
     using (MemoryStream memory = new MemoryStream()) 
     { 
      using (GZipStream zip= new GZipStream(memory, CompressionMode.Compress, true)) 
      { 
       var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
       formatter.Serialize(zip, data); 
      } 

      result = memory.ToArray(); 
     } 

     return result; 
    } 
} 

Luego, acaba de pasar el objeto de transferencia que tendría el nombre del tipo. Por lo que podría hacer algo como esto

[WebMethod] 
public void ReceiveData(TransferObject data) 
{ 
    Type originType = Type.GetType(data.Type); 
    object item = CompressedSerializer.Decompress<object>(data.Data); 
} 

en este momento el serializador comprimido utiliza genéricos para que sea inflexible de tipos, pero se podría hacer un método fácil de tomar en un objeto de tipo deserializar usando originType arriba, todo depende de su implementación.

Espero que esto le de algunas ideas. Ah, y para responder a su otra pregunta, wsdl.exe no admite la reutilización de tipos, sin embargo, WCF sí lo hace.

+0

gracias hombre! No pude comprimir el funcionamiento hasta que noté que leía el flujo de memoria ** después de ** eliminar el flujo de archivos zip. Aparentemente, lavar el flujo de zip no es suficiente ... – dotjoe

1

Darren escribió: I'd do a hybrid. Yo usaría un objeto como este ...

Idea interesante ...pasando una versión serializada del objeto en lugar del propio objeto (wsdl-ed). De alguna manera, me gusta su elegancia, pero de otra manera, parece frustrar el propósito de exponer su servicio web a terceros o socios potenciales o lo que sea. ¿Cómo sabrían qué pasar? ¿Tendrían que depender exclusivamente de la documentación? También pierde algo del aspecto del "cliente heterogéneo", ya que la serialización es muy específica de .Net. No me refiero a ser crítico, solo me pregunto si lo que propones también está destinado a este tipo de casos de uso. Sin embargo, no veo nada de malo en su uso en un entorno cerrado.

Debería mirar en WCF ... Lo he estado evitando, pero tal vez es el momento.

1

oh, claro, solo hago esto cuando soy el consumidor del servicio web o si tiene algún tipo de controlador que solicitan un objeto y luego maneja la serialización y el envío en lugar de que consuman directamente el servicio web. Pero realmente, si consumen directamente el servicio web, entonces no necesitarían o necesariamente tendrían el ensamblado que tendría el tipo en primer lugar, y deberían usar los objetos que genera wsdl.

Y sí, lo que expongo es muy específico de .NET porque no me gusta usar nada más. La única otra vez que consumo servicios web fuera de .net fue en JavaScript, pero ahora solo uso las respuestas json en lugar de las respuestas del servicio web xml :)

Cuestiones relacionadas