Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is your preferred method of sending complex data over a web service?

It's 2008, and I'm still torn on this one. So I'm developing a web method that needs a complex type passed into it and returned from it. The two options I'm toying with are:

  1. Pass and return actual business objects with both data and behavior. When wsdl.exe is run, it will automatically create proxy classes that contain just the data portion, and these will be automatically converted to and from my real business objects on the server side. On the client side, they will only get to use the dumb proxy type, and they will have to map them into some real business objects as they see fit. A big drawback here is that if I "own" both the server and client side, and I want to use the same set of real business objects, I can run into certain headaches with name conflicts, etc. (Since the real objects and the proxies are named the same.)

  2. Forget trying to pass "real" business objects. Instead, just create simple DataTransfer objects which I will map back and forth to my real business objects manually. They still get copied to new proxy objects by wsdl.exe anyway, but at least I'm not tricking myself into thinking that web services can natively handle objects with business logic in them.

By the way - Does anyone know how to tell wsdl.exe to not make a copy of the object? Shouldn't we be able to just tell it, "Hey, use this existing type right over here. Don't copy it!"

Anyway, I've kinda settled on #2 for now, but I'm curious what you all think. I have a feeling there are way better ways to do this in general, and I may not even be totally accurate on all my points, so please let me know what your experiences have been.

Update: I just found out that VS 2008 has an option to reuse existing types when adding a "Service Reference", rather than creating brand new identical type in the proxy file. Sweet.

like image 363
jeremcc Avatar asked Aug 16 '08 03:08

jeremcc


People also ask

What happens to the dataset when a web service is called?

The DataSet will be marshaled back to the client calling the Web Service, so the client can pick up the object with the same data and object attributes as the DataSet passed down from the server. To consume the Web Service on the client side, we have to (again, refer to the previous article if this is new to you):

How to lock down a complex types web service?

For example, to lock the Web Service down to be accessible only by Adminstrative users, go into Explorer on the Server, find the ComplexTypes Web Service on disk, and remove all the security access except for the Administrators group from the ComplexTypes.asmx. Apply the changes and run the Web Service client applications.

What are the advantages of a tightly coupled web service interface?

The web service interface can support innovation over time without negotiating the client's ability to communicate with the service. A tightly coupled system means that the client and server logic are closely tied to one another, indicating that if one interface changes, then another must be updated.

What are the different types of web services?

There are mainly two types of web services. SOAP web services. RESTful web services. Web services use XML at data description and data transportation layers. Using XML exclude any networking, operating system, or platform binding. Web services-based operation is extremely interoperable at their core level.


1 Answers

I'd do a hybrid. I would use an object like this

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

then i have a nice little utility that serializes an object then compresses it.

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

Then you'd just pass the transfer object that would have the type name. So you could do something like this

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

right now the compressed serializer uses generics to make it strongly typed, but you could make a method easily to take in a Type object to deserialize using originType above, all depends on your implementation.

hope this gives you some ideas. Oh, and to answer your other question, wsdl.exe doesn't support reusing types, WCF does though.

like image 51
Darren Kopp Avatar answered Sep 22 '22 16:09

Darren Kopp