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:

[WebMethod]
  public byte[] GetImageBytes(string strImageName)
  {
   ImageClass ic=new ImageClass();   
   FileStream fs = new FileStream(Server.MapPath(strImageName), 
FileMode.OpenOrCreate, FileAccess.Read); Byte[] img= new Byte[fs.Length ]; try { fs.Read(img, 0, Convert.ToInt32(fs.Length)); } catch(Exception ex) { Debug.WriteLine(ex.Message+ex.StackTrace); } fs.Close(); ic.myImage=img; BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms,ic); return ms.ToArray(); } [WebMethod] public ImageClass GetImage(string strImageName) { ImageClass ic=new ImageClass(); FileStream fs = new FileStream(Server.MapPath(strImageName),
FileMode.OpenOrCreate, FileAccess.Read); Byte[] img= new Byte[fs.Length ]; try { fs.Read(img, 0, Convert.ToInt32(fs.Length)); } catch(Exception ex) { Debug.WriteLine(ex.Message+ex.StackTrace); } fs.Close(); ic.myImage=img; return ic; }

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:

using System;
using System.Reflection;
using System.Drawing;
namespace ImageClassAssy
{
 [Serializable]
 public class ImageClass
  {
    public byte[] myImage;
    public 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:

private void button1_Click(object sender, System.EventArgs e)
  {
   // GetImage Method
   BinaryFormatterSvc.Service1 s= new BinaryFormatterSvc.Service1();   
      BinaryFormatterSvc.ImageClass icc=s.GetImage(this.textBox1.Text);   
   byte[] byt=icc.myImage;
   MemoryStream ms = new MemoryStream(byt);
   Bitmap b=(Bitmap) Image.FromStream(ms);
   pictureBox1.Image=b;    
  }
  private void button2_Click(object sender, System.EventArgs e)
  {
   //GetImageBytes (BinaryFormatter) method
   BinaryFormatterSvc.Service1 s= new BinaryFormatterSvc.Service1();      
   byte[] byt=s.GetImageBytes(this.textBox1.Text);
   MemoryStream ms = new MemoryStream(byt);
   BinaryFormatter bf= new BinaryFormatter();
   ImageClass ic=(ImageClass)bf.Deserialize(ms);
   MemoryStream ms2 = new MemoryStream(ic.myImage);
   Bitmap b=(Bitmap) Image.FromStream(ms2);
   pictureBox1.Image=b; 
  }

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.

download the Visual Studio 2003 Solution that accompanies this article

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值