Сведения о вопросе

SOON

08:42, 18th August, 2020

Теги

.net   web-services   soap   wsdl    

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

Просмотров: 430   Ответов: 4

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

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

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

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

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

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



  Сведения об ответе

JUST___

15:24, 29th August, 2020

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

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

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

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


  Сведения об ответе

crush

04:20, 20th August, 2020

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

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


  Сведения об ответе

piter

18:55, 4th August, 2020

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

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

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


  Сведения об ответе

SKY

03:35, 28th August, 2020

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

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


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться