Какой способ отправки сложных данных вы предпочитаете через веб-сервис?

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

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

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

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

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

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

16.08.2008 03:58:24
4 ОТВЕТА
РЕШЕНИЕ

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

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

1
22.09.2015 04:56:12

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

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 поддерживает.

4
16.08.2008 04:31:53
Спасибо чувак! Я не мог заставить работать компрессор, пока не заметил, что вы читаете поток памяти после удаления потока zip. Видимо, промывки потока zip недостаточно ...
dotjoe 5.02.2010 22:15:25

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

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

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

1
16.08.2008 04:56:42

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

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

1
16.08.2008 05:16:55