Sunday, February 3, 2013

Image Upload and Preview Control in ASP.NET Ajax

Image upload and previewing is a very basic requirement usually when we come across user registration page or add and edit an institution, etc. In this post I am providing here the sample which does the same using ASP.NET Ajax.

I had given here just a simple example just to upload and preview the image, I am not going to save the image in the Database or Load from the Database, but of course you can extend this control based on your requirements.

This is how the final screen will look once you complete the code:


You will need Ajax Control Toolkit for AsyncFileUpload control, this controls helps to perform the asynchronous operation without page refresh. Best way to get this through NuGet package manager in you project.

Now lets see the ASP.NET Page and the Code Behind for that.

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="UploadImage.aspx.cs" Inherits="UploadImage" %>
   6: <!DOCTYPE html>
   8: <html xmlns="">
   9: <head runat="server">
  10:     <title></title>
  12:     <script language="javascript" type="text/javascript">
   2:         function getRandomNumber() {
   3:             var randomnumber = Math.random(10000);
   4:             return randomnumber;
   5:         }
   7:         function OnClientAsyncFileUploadComplete(sender, args) {
   8:             var handlerPage = '<%= Page.ResolveClientUrl("~/ImageRequestHandler.ashx")%>';
   9:             var queryString = '?randomno=' + getRandomNumber() + '&action=preview';
  10:             var src = handlerPage + queryString;
  11:             var clientId = '<%=previewImage.ClientID %>';
  12:         document.getElementById(clientId).setAttribute("src", src);
  13:     }
  14: </head>
  15: <body>
  16:     <form id="form1" runat="server">
  17:         <ajaxToolkit:ToolkitScriptManager ID="toolKitScriptManager" runat="server">
  18:         </ajaxToolkit:ToolkitScriptManager>
  19:         <div>
  20:             <asp:Panel ID="pFileUpload" runat="server">
  21:                 <label>
  22:                     Image Source:</label>
  23:                 <ajaxToolkit:AsyncFileUpload ID="asyncFileUpload" runat="server" 
  24:                     OnClientUploadComplete="OnClientAsyncFileUploadComplete"
  25:                     OnUploadedComplete="OnAsyncFileUploadComplete" Width="374px" />
  26:                 <br />
  27:                 <asp:Image runat="server" ID="previewImage" Width="150px" BorderStyle="Double" BorderColor="Green" />
  28:             </asp:Panel>
  29:         </div>
  30:     </form>
  31: </body>
  32: </html>

The code above is very simple and self explanatory, still let me quickly give you a walkthrough. In the Script section of this page I am writing an function which gets called by the AsyncFileUpload control once the file upload to server is completed. Basically in Server side we are just saving the image temporarily in Session which is referenced in Handler section which I am going to cover very soon. In the same function we are calling the ImageHandler which gets the image from the session as mentioned above and write the image to response stream. Once the operation is over this function maps the source to the image control in the client side.

While calling the Image Handler sometimes in certain cases the browser caches the response stream due to which we may face the problem in refreshing the images. To overcome this you can see In the same script I have used a function to generate a random number which basically used to get the unique URL to call the ImageHandler and overcome the response caching issue.

I have almost explained the entire functionality still lets look into the ImagePreviewHandler and Code Behind part of the application.

   1: protected void OnAsyncFileUploadComplete(object sender, AsyncFileUploadEventArgs e)
   2: {
   3:     if (asyncFileUpload.FileBytes != null)
   4:     {
   5:         Context.Session.Add("SessionImage", asyncFileUpload.FileBytes);
   6:     }
   7: }
   1: <%@ WebHandler Language="C#" Class="ImageRequestHandler" %>
   2: using System;
   3: using System.Web;
   5: public class ImageRequestHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
   6: {
   7:     public void ProcessRequest(HttpContext context)
   8:     {
   9:         context.Response.Clear();
  11:         if (context.Request.QueryString.Count != 0)
  12:         {
  13:             byte[] imageData = context.Session["SessionImage"] as byte[];
  15:             if (imageData != null)
  16:             {
  17:                 context.Response.OutputStream.Write(imageData, 0, imageData.Length);
  18:                 context.Response.ContentType = "image/JPEG";
  19:             }
  20:         }
  21:     }
  23:     public bool IsReusable {
  24:         get {
  25:             return false;
  26:         }
  27:     }
  29: }

In the first snippet I have given the code behind of the ASP.NET page, which simple saves the image byte array into the Session in the  OnUploadedComplete  event of AsyncFileUpload control. This image byte array is used later in Image Handler to process further.

And finally in the second snippet I am showing the ASP.NET Generic Handler, in ProcessRequest I am fetching the image byte array from the Session and writing the image to the response of the page. A part from implementing IHttpHandler, I am also deriving the System.Web.SessionState.IRequiresSessionState, which provides me the ability to read and write to the session. This is very important in our case since we are using session variable to read the images in the Image Request Handler.

And that all we need. You can download the code from here.