Qual é o seu método preferido para enviar dados complexos por meio de um serviço da web?

StackOverflow https://stackoverflow.com/questions/12982

  •  08-06-2019
  •  | 
  •  

Pergunta

Estamos em 2008 e ainda estou indeciso quanto a isso.Então, estou desenvolvendo um método web que precisa de um tipo complexo passado e retornado dele.As duas opções com as quais estou brincando são:

  1. Passe e retorne real objetos de negócios com dados e comportamento.Quando wsdl.exe for executado, ele criará automaticamente classes de proxy que contêm apenas a parte dos dados, e estas serão automaticamente convertidas de e para meus objetos de negócios reais no lado do servidor.No lado do cliente, eles só poderão usar o tipo de proxy burro e terão que mapeá-los em alguns objetos de negócios reais conforme acharem adequado.Uma grande desvantagem aqui é que, se eu "possuir" o lado do servidor e do cliente e quiser usar o mesmo conjunto de objetos de negócios reais, posso ter certas dores de cabeça com conflitos de nomes, etc.(Uma vez que os objetos reais e os proxies têm o mesmo nome.)

  2. Esqueça a tentativa de passar objetos de negócios "reais".Em vez disso, basta criar objetos DataTransfer simples que mapearei manualmente para meus objetos de negócios reais.De qualquer forma, eles ainda são copiados para novos objetos proxy pelo wsdl.exe, mas pelo menos não estou me enganando pensando que os serviços da Web podem lidar nativamente com objetos com lógica de negócios.

A propósito - Alguém sabe como dizer ao wsdl.exe para não fazer uma cópia do objeto?Não deveríamos ser capazes de dizer: “Ei, use este tipo existente bem aqui.Não copie!"

De qualquer forma, decidi pelo número 2 por enquanto, mas estou curioso para saber o que todos vocês pensam.Tenho a sensação de que existem caminho melhores maneiras de fazer isso em geral, e posso até não ser totalmente preciso em todos os meus pontos, então, por favor, deixe-me saber quais foram suas experiências.

Atualizar:Acabei de descobrir que o VS 2008 tem a opção de reutilizar tipos existentes ao adicionar uma "Referência de serviço", em vez de criar um novo tipo idêntico no arquivo proxy.Doce.

Foi útil?

Solução

há também um argumento para separar as camadas - ter um conjunto de objetos serializáveis ​​que são passados ​​de e para o serviço da web e um tradutor para mapear e converter entre esse conjunto e os objetos de negócios (que podem ter propriedades não adequadas para passar pelo arame)

É a abordagem preferida pela fábrica de software de serviços web fábrica de serviços e significa que você pode alterar seus objetos de negócios sem quebrar a interface/contrato do serviço web

Outras dicas

Eu faria um híbrido.Eu usaria um objeto como este

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

então eu tenho um pequeno utilitário que serializa um objeto e depois o compacta.

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

Então você simplesmente passaria o objeto de transferência que teria o nome do tipo.Então você poderia fazer algo assim

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

no momento, o serializador compactado usa genéricos para torná-lo fortemente tipado, mas você pode criar um método facilmente para receber um objeto Type para desserializar usando originType acima, tudo depende da sua implementação.

Espero que isso te dê algumas ideias.Ah, e para responder à sua outra pergunta, wsdl.exe não suporta a reutilização de tipos, mas o WCF suporta.

Darren escreveu:Eu faria um híbrido.Eu usaria um objeto como este ...

Ideia interessante...passando uma versão serializada do objeto em vez do próprio objeto (wsdl-ed).De certa forma, gosto da sua elegância, mas por outro lado, parece ir contra o propósito de expor o seu serviço web a potenciais terceiros ou parceiros ou o que quer que seja.Como eles saberiam o que passar?Eles teriam que confiar apenas na documentação?Também perde um pouco do aspecto de "cliente heterogêneo", já que a serialização é muito específica do .Net.Não quero ser crítico, só estou me perguntando se o que você está propondo também se aplica a esses tipos de casos de uso.Não vejo nada de errado em usá-lo em um ambiente fechado.

Eu deveria dar uma olhada no WCF ...Tenho evitado isso, mas talvez seja a hora.

ah, com certeza, eu só faço isso quando sou o consumidor do serviço da web ou se você tem algum tipo de controlador do qual eles solicitam um objeto e então você cuida da serialização e do envio, em vez de consumir diretamente o serviço da web.Mas, na verdade, se eles estão consumindo diretamente o webservice, então eles não precisariam ou necessariamente teriam o assembly que teria o tipo nele e deveriam usar os objetos que o wsdl gera.

E sim, o que apresentei é muito específico do .NET porque não gosto de usar mais nada.A única outra vez que consumi webservices fora do .net foi em javascript, mas agora só uso respostas json em vez de respostas de webservice xml :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top