Streaming Databased Images Using HttpHandler
For a long time now I have noticed something annoying when working on Web Application projects involving databased images on my local machine. By local I mean that it's a typical environment with VS 2008 and SQL Server 2005 on my workstation. Whenever I use an HttpHandler to display the images on my local, only some of the images render on each page load.
However, when I push the application to a hosted environment, the problem usually disappears. However, I just pushed a new project out to a hosted environment and experienced the same problem as on my local - this time the site and the DB were on the same server in the hosting environment. Has anyone got a take on what's happening here?
Here's the handler:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class FeaturedHandler : IHttpHandler
{
Business biz = new Business();
public void ProcessRequest(HttpContext context)
{
if (context.Request.QueryString["ListingID"] != null)
{
int listingID = Convert.ToInt32(context.Request.QueryString["ListingID"]);
DataSet ds = biz.GetFeaturedImageByID(listingID);
DataRow row = ds.Tables[0].Rows[0];
byte[] featureImage = (byte[])row["Photo"];
context.Response.ContentType = "image/jpeg";
context.Response.OutputStream.Write(featureImage, 0, featureImage.Length);
}
else
throw new ArgumentException("No ListingID parameter specified");
}
public bool IsReusable
{
get
{
return false;
}
}
}
I have tried using a DB on a separate server but encountered the same problem. Should I be using a DataReader instead?
UPDATE I should have used a DataReader initially since I am reading binary data.
I finally got all images to render by changing the value of the IsReusable property to true:
public bool IsReusable
{
get
{
return true;
}
}
Apparently, this keeps the handler in memory and able to handle multiple requests. When set to false, it had to create a new instance of the handler for each incoming request.
By this:
Whenever I use an HttpHandler to display the images on my local, only a portion of the images render on each page load.
Do you mean that the same image appear on places where different images should appear or that some images appear and some doesn't show at all?
In your case the difference by switching isReusable
to true is that new Business();
will be called once for multiple images. If isReusable
is false the new Business();
will be called once per image. This means that if you have several images per page new Business();
will be called several times for this particular page.
Also I strongly suggest changing this:
if (context.Request.QueryString["ListingID"] != null)
{
int listingID = Convert.ToInt32(context.Request.QueryString["ListingID"]);
with:
string listingIdParam = context.Request.QueryString["ListingID"];
if (listingIdParam != null)
{
int listingID = Convert.ToInt32(listingIdParam);
This will save you null reference exceptions that usually surface only under heavy load. Also the above will prevent serving the wrong image to a request especially when isReusable is true.
I cannot determine what the problem was exactly but I can definitely say that setting the isReusable flag was just a workaround and doesn't fix your problem. Also when a problem like this is reproducible only in certain environment that means that either it's a thread problem or there is some difference in request handling (different web server - IIS6, IIS7, development server).
Maybe posting the Business
class and it's constructor can shed some light.
Also I suggest implementing some kind of error logging to trap exceptions in the handler and review them.