Tuesday, September 19, 2006 2:21 AM bart

An ASP.NET .ashx HTTP handler for Code 39 barcode generation

Introduction

In my previous blog post on Code 39 barcodes, I've shown you guys how to generate Code 39 barcodes using managed code. Today, we'll take it another step forward and make barcode generation available through an .ashx ASP.NET 2.0 HTTP handler.

About ASP.NET 2.0 Generic Handlers

One of the great things in ASP.NET is the concepts of "generic handlers". Basically you can look at it as just another kind of object that can process HTTP requests, however outside the scope of a page (which targets 'classic' HTML-based output). You might have heard about HTTP handlers too and basically these are the same except for the fact that you can bind an HTTP handler to any file extension (as long as you IIS configuration permits) whileas a generic handler just lives behind the .ashx extension and is directly supported in Visual Studio 2005 web site projects. In the end all handlers implement System.Web.IHttpHandler. Last but not least, you'll be able to host any ASP.NET HTTP Handler directly in IIS 7 too (which I'll blog about later on).

Our online Code39 barcode generator

First of all create a new web site project in Visual Studio 2005:

Next, add a new generic handler called "Code39Generator.ashx" to the project:

This will generate the following piece of code:

<%@ WebHandler Language="C#" Class="Code39Generator" %>

using
System;
using
System.Web;

public
class Code39Generator : IHttpHandler {
   public void ProcessRequest (HttpContext
context) {
      context.Response.ContentType =
"text/plain"
;
      context.Response.Write(
"Hello World"
);
   }

   public bool
IsReusable {
      get
{
         return false
;
      }
   }
}

Exactly, "Hello World" made it to the built-in code snippets in Visual Studio 2005. Our task is to create a suitable ProcessRequest method that returns an image with a requested barcode. Requested by means of the querystring that is. The IsReusable property is used by the ASP.NET runtime to find out whether the instance of our handler can be reused for multiple requests. That's fine for us, as we don't have intentions to turn our handler instance to garbage once a request has passed through the pipeline:

   public bool IsReusable {
      get
{
         return true
;
      }
   }

On to the real stuff now. First of all make sure the Code39 and Code39Settings classes (see previous post) are available in the context of the web site project. You can do that by CTRL-C,V-ing the code to a class file or by referencing a class library project. I've chosen to walk the former path as shown below:

Make sure to declare the classes as follows:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;

public
class Code39Settings
{
   ...
}

public class
Code39
{
   ...
}

Back to our .ashx file. First let's fix some namespace imports:

using System;
using
System.Web;
using
System.IO;
using
System.Drawing;
using System.Drawing.Imaging;

Real stuff happens a little further, in the ProcessRequest method which we define like this:

public void ProcessRequest(HttpContext context)
{
  
string code = context.Request["code"
];
   if (code != null
)
   {
      Image img = new Code39
(code.ToUpper()).Paint();
      context.Response.ContentType =
"image/png"
;
      byte
[] b = GetImageBytes(img);
      context.Response.OutputStream.Write(b, 0, b.Length);
   }
}

The basic idea is simple: just take the generated image from our Code39 class's Paint method and send it back to the client as an image/png type of HTTP response. In order to do so, we'll need the bytes of the image.

Note: It would be easier if we could write this:

img.Save(context.Response.OutputStream, ImageFormat.Png);

However this causes the following exception to occur:

[ExternalException (0x80004005): A generic error occurred in GDI+.]
   System.Drawing.Image.Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) +568
   System.Drawing.Image.Save(Stream stream, ImageFormat format) +33
   Code39Generator.ProcessRequest(HttpContext context) +157
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +390
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +65

There are lots of forum threads on this issue (just Live Search for it), most of which have to do with permissions when trying to save images on the server's disk. However, I decided to create a code-based workaround as I have some indications permissions might not be the issue in this case (and even if they were, I rather like to have the solution just work in xcopy deployment scenarios). Therefore, here it is, the GetImagesBytes method:

private byte[] GetImageBytes(Image image)
{
   ImageCodecInfo codec = null
;

   foreach (ImageCodecInfo e in ImageCodecInfo
.GetImageEncoders())
   {
      if (e.MimeType == "image/png"
)
      {
         codec = e;
         break
;
      }
   }

   using (EncoderParameters ep = new EncoderParameters
())
   {
      ep.Param[0] =
new EncoderParameter(Encoder
.Quality, 100L);

      using (MemoryStream ms = new MemoryStream
())
      {
         image.Save(ms, codec, ep);
         return
ms.ToArray();
      }
   }
}

This one just works fine. So, press F5 to run the web site project and see the ASP.NET Development Server getting ready to serve you:

Right-click the icon and choose "Open in Web Browser" if the system didn't do this already by itself. You should see the directory listing now:

Click the Code39Generator.ashx file and patch the browser address bar by appending ?code=BART to it (e.g. http://localhost:49587/Code39/Code39Generator.ashx?code=BART - the port will much likely be different on your machine). There we go:

Stay tuned for even more barcode fun soon!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under: , ,

Comments

# An ASP.NET .ashx HTTP handler for Code 39 barcode generation

Tuesday, September 19, 2006 7:31 AM by It's Way Too Early For This

I dig Bart's contributions. Here's yet another one. A follow on to his previous post on the Code 39 Barcode

# EAN-13 barcodes in C#

Tuesday, September 19, 2006 6:11 PM by B# .NET Blog

Introduction
A couple of days ago I posted about Code 39 barcode generation in C#&amp;nbsp;(and here). Today...

# Creating Barcodes On The Fly With C#

Monday, October 02, 2006 10:06 PM by Tom's corner

# Creating Barcodes On The Fly With C#

Friday, October 06, 2006 6:04 AM by It's Way Too Early For This

I had a couple of pointers to two of these articles, but here is the whole catalog of barcode code from

# re: An ASP.NET .ashx HTTP handler for Code 39 barcode generation

Sunday, October 15, 2006 7:12 PM by papes510

Great work thanks a lot. Just a small issue, when i try to print the page the barcodes appear as solid black boxes. if i import the file into fireworks and set canvas to 'white' it fixes the problem. any ideas?

Thanks!

# re: An ASP.NET .ashx HTTP handler for Code 39 barcode generation

Sunday, October 15, 2006 8:59 PM by bart

I can't directly repro the issue over here (i.e. things print fine). You might want to do some experiments with

Bitmap bmp = new Bitmap(w, h, PixelFormat.Format32bppArgb);

in Code39.cs

and the codec selection in the .ashx file to experiment with different output formats:

foreach (ImageCodecInfo e in ImageCodecInfo.GetImageEncoders())
{
  if (e.MimeType == "image/png")
  {
     codec = e;
     break;
  }
}

# re: An ASP.NET .ashx HTTP handler for Code 39 barcode generation

Wednesday, October 25, 2006 12:27 AM by papes510

Hey, Ok so i figured out that firefox doesnt like png files very much. That was the reason it printed black, it works perfectly in IE though. The only thing is in IE it prints with a light blue background. I tried changing the format to "image/jpeg" but it didnt even display the image like that. Any ideas? Thanks!

# Code 39 in C# &laquo; .NET i takie tam

Monday, June 18, 2007 8:47 AM by Code 39 in C# « .NET i takie tam

Pingback from  Code 39 in C# &laquo; .NET i takie tam

# http://community.bartdesmet.net/blogs/bart/archive/2006/09/19/4450.aspx