Introduction
While developing client/server applications, you often need to send an object to your client. The easiest way for us programmers to work with an object would be to get the whole object from the server, not just some properties.
One way to do this is to use WCF or Web Services, which give you a whole set of tools, like serialization to accomplish this task, but these set of technologies often bring a lot of overhead and complexities to your project, that often you would not want if what you're doing is just sending and receiving one or more objects.
Faced with this dilemma, I spent some time looking for a solution to this; my goal was to find a very easy, simple, and clean way to create an object on the server, serialize it, and send it back to the client. Security and interoperability were not a concern at this point, but they could be implemented later. The constraints for this were that it had to be fast and it had to work through the basic HTTP protocol.
My solution was to create an ASP.NET page that reads the query string to determine what object to return, creates the object, serializes it to binary, and returns it as a binary attachment to the client. The client downloads this file using the WebClient()
class and deserializes it back to the object.
Both the server and the client share a class library containing the common object. At first, I implemented this using XML serialization, but found that it is quite slow, but it could also be used if you require interoperability.
Background
Bear in mind that this is not the only way to do this; you probably can do it with WCF using a custom binding or using MTOM, but I found in my experience that these methods were too involved and added unnecessary complexity for simple projects.
Using the Code
On the web server page load, we include code to check which object the client is requesting, and return the serialized object as a binary attachment.
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["op"] == "getdata")
{
var data = new SampleData();
data.moreData = 34343;
data.otherData = true;
data.SomeData = "fewoifjweofjwepo";
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition",
"attachment; filename=sampleData.bin");
var binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(Response.OutputStream, data);
Response.End();
}
On the client, we create the request to the server using a query string, and deserialize the response.
string url = "http://localhost/BinaryServiceSample/Default.aspx?op=getdata";
var client = new WebClient();
byte[] result = client.DownloadData(url);
var mem = new MemoryStream(result);
var binaryFormatter = new BinaryFormatter();
var data = (SampleData)binaryFormatter.Deserialize(mem);
mem.Close();
Console.Write(data.ToString());
Console.ReadLine();
Points of Interest
- Although binary serialization may "feel" more comfortable, it may not be compatible across different platforms.
- Serializing objects using binary serialization is way faster than XML.
- This code does not include any error handling, this is something that could be easily incorporated into it. I did not include it to make it more clear and simple.
- One way to add security is to encrypt the actual bytes before sending them to the client; this, of course, would make interoperability very difficult.
- Additional transport speed could be obtained by compressing the bytes before sending them; I know ICSharpCode.SharpZipLib.dll can compress in memory bytes, and it is free, but you could also do it with the .NET Framework by implementing HTTP compression and embedding it into your code - check out this article for an example: http://www.codeproject.com/Articles/38067/Compress-Response.aspx.
- Serializing an object like this seems to give me more control over how things are done without adding too much complexity.
I would like to receive comments, suggestions, and constructive criticism about this, if you have any, or any improvements, please let me know so I can include them.
Thanks to Andre Sanches for his contributions to this article.