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

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

  •  08-06-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

Обновить:Я только что узнал, что в VS 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;
    }
}

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top