Binary Serialization and BinaryFormatter with WebServices
"The Semantic Web is not a separate Web but an extension of the current one, in which information is given well-defined meaning, better enabling computers and people to work in cooperation." -- Sir Tim Berners-Lee
Recently we have had some forum posts with questions that generally seem to revolve around the topic of "How do I serialize and send an image over a WebService" and "BinaryFormatter doesn't work - gives Assembly Version exception".
Rather than launch into a repetitious tirade of post-answering, I thought it might be a good time to examine this with some carefully considered sample code. What I've done here is to create a simple WebService that has two methods -
1) GetImage - Accepts a string for the image fileName (assumes Server.MapPath), reads the image off the file system into a Byte array, and then sticks it into the public byte "myImage" property of a simple serializable class, "ImageClass". This class is sent in its entirety as the return type from the method.
2) GetImageBytes - This method does exactly what the first method does, except that it use the BinaryFormatter to serialize the ImageClass instance , and sends the resultant byte array to the caller.
There are significant advantages to first storing our image in a property of a class instance and serializing the entire class, not the least of which is that we can have additional information besides "just the image" getting serialized and sent over the wire.
The method details of these two WebMethods follow:
The ImageClass needs to be put into a separate class library project that is referenced from the WebService class (as well as by the caller). This is how we prevent BinaryFormatter "Assembly" errors, because when we attempt to deserialize the output of the Formatter, the Assembly name, version and cultureInfo will all match. If you attempt to put your ImageClass class into the actual WebService project, this is what will cause you unnecessary headaches. The same goes for interfaces with remoting - need to get that serializable "thing" into a separate class library. So now here is the code for the ImageClass:
Now for our test harness, we will use a Windows Forms app that uses a WebReference to our service, and has two buttons - one to exercise each method. Here is the code for each button, respectively:
The result of our method call, with my handy "Pete.jpg" image sitting on the server, would look like so:
And, just in case you missed my first point, let's not forget to add a reference to our ImageClass assembly in our Winforms app, so that our client will know how to and "into what" to deserialize the type it has received and get out the image property for display.