by: bipin joshi level: intermediate posted date: 5/31/2002 tested with asp.net v1.0 (rtm) click for printable version click here to download sample code
member rating: 3.90 (rated by 10 members) rate this item asp.net web services provide 'web callable' functions based on industry standards like http, xml and soap. since web services heavily rely on xml, all the data that is passed to and returned from a web service must be plain text. however, in certain applications we do need to pass binary data. say for example i want to pass images from my web form to a web service to save in some central repository and then retrieve them back. does this mean that web services cannot be used for such data transfer? certainly not. in fact asp.net web services make it easy to pass such data by hiding the encoding and decoding involved. typically when you want to pass binary data you will declare the parameter of the web method or return value of the web method as a byte array. asp.net web services will automatically encode/decode this data using base64 encoding. (base64 encoding is the same encoding that is used for email mime attachments.) in this example we develop an image upload web service that stores and retrieves images from sql server database. sql server database table to work with example you need a table in sql server database called images. the following script can be used to create this table. create table [dbo].[images] ( [id] [int] identity (1, 1) not null , [imgdata] [image] null ) on [primary] textimage_on [primary] the table contains two columns - id that represents the primary key and imgdata that stores binary image data. note that i have created this table in northwind database itself; you may want to create it in some other database. creating the web service now, let us proceed with creating the web service. create a new web service project in vs.net and add the following two web methods to it. <webmethod()> public function saveimage(byval imgdata() as byte) as string dim connstr as string = "integrated security=sspi;user id=sa;initial catalog=northwind;data source=server/netsdk" dim cnn as new sqlconnection(connstr) cnn.open() dim cmd as new sqlcommand("insert into images values(@img)", cnn) cmd.parameters.add(new sqlparameter("@img", imgdata)) cmd.executenonquery() end function <webmethod()> public function retrieveimage(byval imgid as integer) as byte() dim connstr as string = "integrated security=sspi;user id=sa;initial catalog=northwind;data source=server/netsdk" dim cnn as new sqlconnection(connstr) dim cmd as new sqlcommand("select * from images where id=" & imgid, cnn) cnn.open() dim dr as sqldatareader = cmd.executereader dr.read() dim bindata() as byte = dr.getvalue(1) return bindata end function the method saveimage accepts a byte array containing image data and saves it to the images table. the second method accepts image id to be retrieved and returns a byte array from the web method. next, we will develop a web client that presents ui for uploading files and calls this web service internally. creating the client for the web service create a new web application in vs.net and add a web reference to the web service we developed in the previous sections. now, add a new webform called webform1 to the project. put a file html server control and button web control on the form. the form should look like this:
the following is the markup of the webform: <%@ page language="vb" autoeventwireup="false" codebehind="webform1.aspx.vb" inherits="binarydatawc.webform1"%> <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> <html> <head> <title>webform1</title> <meta name="generator" content="microsoft visual studio.net 7.0"> <meta name="code_language" content="visual basic 7.0"> <meta name="vs_defaultclientscript" content="javascript"> <meta name="vs_targetschema" content="http://schemas.microsoft.com/intellisense/ie5"> </head> <body ms_positioning="gridlayout"> <form id="form1" method="post" runat="server" enctype="multipart/form-data"> <input style="z-index: 101; left: 164px; position: absolute; top: 51px" type="file" id="file1" name="file1" runat="server"> <asp:label id="label1" style="z-index: 103; left: 22px; position: absolute; top: 48px" runat="server">select file to upload :</asp:label> <asp:button id="button1" style="z-index: 102; left: 180px; position: absolute; top: 94px" runat="server" text="upload"></asp:button> </form> </body> </html> note that the form has enctype attribute set to multipart/form-data. this is necessary in order to upload files. now, write the following code in the click event of the upload button: private sub button1_click(byval sender as system.object, byval e as system.eventargs) handles button1.click dim ws as new localhost.service1() dim s as stream = file1.postedfile.inputstream dim data(file1.postedfile.contentlength - 1) as byte s.read(data, 0, file1.postedfile.contentlength) ws.saveimage(data) end sub here, we have created instance of web service class (actually proxy class). we fetched the file content into a byte array and then pass this array to the saveimage web method. it's time now to develop another webform that will retrieve images from the database.
add a new webform to the project called webform2 and put a label, textbox, button and image web control on it. the textbox is used to specify the image id to be retrieved. we will retrieve the image as a byte array, save it in some file and then bind the image web control to the file. the following is the markup of the webform: <%@ page language="vb" autoeventwireup="false" codebehind="webform2.aspx.vb" inherits="binarydatawc.webform2"%> <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> <html> <head> <title>webform2</title> <meta name="generator" content="microsoft visual studio.net 7.0"> <meta name="code_language" content="visual basic 7.0"> <meta name="vs_defaultclientscript" content="javascript"> <meta name="vs_targetschema" content="http://schemas.microsoft.com/intellisense/ie5"> </head> <body ms_positioning="gridlayout"> <form id="form1" method="post" runat="server"> <asp:button id="button1" style="z-index: 102; left: 271px; position: absolute; top: 29px" runat="server" text="retrieve"></asp:button> <asp:label id="label1" style="z-index: 104; left: 31px; position: absolute; top: 31px" runat="server">image id :</asp:label> <asp:textbox id="textbox1" style="z-index: 103; left: 108px; position: absolute; top: 30px" runat="server"></asp:textbox> <asp:image id="image1" style="z-index: 101; left: 28px; position: absolute; top: 70px" runat="server"></asp:image> </form> </body> </html> write the following code in the click event of retrieve button: private sub button1_click(byval sender as system.object, byval e as system.eventargs) handles button2.click dim ws as new localhost.service1() dim data() as byte = ws.retrieveimage(textbox1.text) dim s as new filestream(server.mappath(request.applicationpath) & "/sample.jpg", filemode.create) s.write(data, 0, data.length) s.close() image1.imageurl = server.mappath(request.applicationpath) & "/sample.jpg" end sub here, we have created a disk file to hold the retrieved bytes. the following screen shows a sample run of the webform.
summary in this article we saw how to develop an image upload web service. web services are based on standards like xml and soap that are 'text only'. however, asp.net web services make it easy to pass binary data to and from the web service by automatically encoding the data using base64 encoding.