Какой способ отправки сложных данных вы предпочитаете через веб-сервис? - PullRequest
9 голосов
/ 16 августа 2008

Это 2008 год, и я все еще разрываюсь на этом. Поэтому я разрабатываю веб-метод, которому нужен сложный тип, переданный в него и возвращенный из него. Я играю с двумя вариантами:

  1. Передача и возврат фактических бизнес-объектов с данными и поведением. Когда wsdl.exe запущен, он автоматически создаст прокси-классы, которые содержат только часть данных, и они будут автоматически преобразованы в мои реальные бизнес-объекты на стороне сервера и обратно. На стороне клиента они будут использовать только тупой тип прокси, и им придется сопоставлять их с некоторыми реальными бизнес-объектами по своему усмотрению. Большим недостатком здесь является то, что, если я «владею» как серверной, так и клиентской сторонами и хочу использовать один и тот же набор реальных бизнес-объектов, я могу столкнуться с определенными головными болями с конфликтами имен и т. Д. (Поскольку реальные объекты и прокси называются одинаково.)

  2. Забудьте пытаться передать «реальные» бизнес-объекты. Вместо этого просто создайте простые объекты DataTransfer, которые я буду сопоставлять с реальными бизнес-объектами вручную. Они все равно копируются в новые прокси-объекты с помощью wsdl.exe, но, по крайней мере, я не обманываю себя на мысли, что веб-сервисы могут обрабатывать объекты с бизнес-логикой.

Кстати - кто-нибудь знает, как заставить wsdl.exe не сделать копию объекта? Разве мы не можем просто сказать ему: «Эй, используйте этот существующий тип прямо здесь. Не копируйте его!»

Во всяком случае, я пока остановился на №2, но мне любопытно, что вы все думаете. У меня такое ощущение, что есть способ более совершенных способов сделать это в целом, и я, возможно, даже не совсем точен во всех моих пунктах, поэтому, пожалуйста, дайте мне знать, каков был ваш опыт.

Обновление : Я только что обнаружил, что VS 2008 имеет возможность повторно использовать существующие типы при добавлении «Service Reference» вместо создания нового идентичного типа в прокси-файле. Сладкое.

Ответы [ 4 ]

4 голосов
/ 16 августа 2008

Я бы сделал гибрид. Я бы использовал такой объект

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

тогда у меня есть симпатичная маленькая утилита, которая сериализует объект, а затем сжимает его.

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

Тогда вы просто передадите объект переноса, который будет иметь имя типа. Таким образом, вы могли бы сделать что-то вроде этого

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

прямо сейчас сжатый сериализатор использует обобщения, чтобы сделать его строго типизированным, но вы могли бы легко создать метод для использования объекта Type для десериализации с использованием originType выше, все зависит от вашей реализации.

надеюсь, это даст вам некоторые идеи. Да, и чтобы ответить на ваш другой вопрос, wsdl.exe не поддерживает повторное использование типов, хотя WCF поддерживает.

1 голос
/ 21 августа 2008

есть также аргумент для разделения уровней - иметь набор сериализуемых объектов, которые передаются в и из веб-службы, и переводчик для сопоставления и преобразования между этим набором и бизнес-объектами (которые могут иметь свойства, не подходящие для проходя по проводу)

Это подход, одобренный фабрикой программного обеспечения веб-служб фабрика услуг и означает, что вы можете изменять свои бизнес-объекты, не нарушая интерфейс веб-службы / контракт

1 голос
/ 16 августа 2008

о, конечно, я делаю это только тогда, когда я пользуюсь веб-сервисом или если у вас есть какой-то контроллер, от которого они запрашивают объект, а затем вы обрабатываете сериализацию и отправку, а не их непосредственное использование в Интернете. оказание услуг. Но на самом деле, если они напрямую используют веб-сервис, то им не понадобится или не обязательно будет иметь сборку, в которой изначально будет указан тип, и они должны использовать объекты, которые генерирует wsdl.

И да, то, что я выдвинул, очень специфично для .NET, потому что я не люблю использовать что-то еще. Единственный раз, когда я использую веб-сервисы вне .net, был в javascript, но теперь я использую только ответы json вместо ответов xml webservice:)

1 голос
/ 16 августа 2008

Даррен писал: я бы сделал гибрид. Я бы использовал такой объект ...

Интересная идея ... передать сериализованную версию объекта вместо (wsdl-ed) самого объекта. В некотором смысле, мне нравится его элегантность, но, с другой стороны, кажется, что он побеждает цель раскрытия вашего веб-сервиса потенциальным третьим сторонам или партнерам или что-то еще. Как они узнали бы, что пройти? Должны ли они полагаться исключительно на документацию? Он также теряет часть аспекта «гетерогенного клиента», поскольку сериализация очень специфична для .Net. Я не хочу критиковать, мне просто интересно, предназначено ли то, что вы предлагаете, для этих типов использования. Я не вижу ничего плохого в использовании его в закрытой среде.

Я должен посмотреть в WCF ... Я избегал этого, но, возможно, пришло время.

...