|
Some time ago, my site partner Robbe Morris did an in-depth
investigation of
HttpHandlers with respect to performance considerations. One of the things
he did with a handler was to remap a custom image property to a handler
that writes an image to the Response stream in an attempt to bypass the
baggage of the Page class and see what performance gains could be obtained.
There's another useful way to use an image - generating handler,
and that's to gather visitor statistics on a particular page, or even for
your whole site, if you want. It's very efficient, and while it doesn't
have all the features of say, WebTrends, it sure doesn't take up as many
resources either.
The key trick, and it's one that is commonly used in classic
ASP and CGI scripts, is to point the src attribute of an IMG tag not directly
at an image, but at a page (or in this case, an ASHX handler) that does
additional processing and then finally does return an image to make the
IMG tag happy.
So for example, with our new concept, your image tag on
a page that you want to capture visitor statistics on might look like this:
<img id="stats" .src="ImageHandler.ashx?name=whatever.gif" />
Now let's see exactly what my sample
implementation of the hander does with this when it's loaded:
<%@webhandler class='ImageWriter' language='c#'%>
using System;
using System.Web;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.IO;
public class ImageWriter : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
StringBuilder sbLog = new StringBuilder();
HttpBrowserCapabilities bc = ctx.Request.Browser;
sbLog.Append(bc.Type + "," + bc.Browser + "," + bc.Version + "," +bc.Platform + "," );
sbLog.Append(ctx.Request.UrlReferrer +"," +ctx.Request.UserHostAddress + ","
+ ctx.Request.IsAuthenticated + "," + ctx.Request.HttpMethod + "\r\n");
FileInfo fi = new FileInfo(ctx.Server.MapPath("log.txt"));
// use FileMode.Append to not overwrite older entries
FileStream sWriterAppend = fi.Open(FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
sWriterAppend.Write(System.Text.Encoding.ASCII.GetBytes(sbLog.ToString()), 0, sbLog.Length);
sWriterAppend.Flush();
sWriterAppend.Close();
sbLog = null;
fi = null;
sWriterAppend = null;
string sFileName=String.Empty;
string sPath=ctx.Server.MapPath(".");
try
{
sFileName = ctx.Request["name"].ToString().Trim();
if (sFileName.Length <5) { return; } // must be at least "1.gif" (5 chars)
ctx.Response.WriteFile(sPath+ @"\images\" + sFileName);
}
catch (Exception e) {
ctx.Response.Write(e.Message);
}
}
public bool IsReusable { get { return true; } }
} |
OK, here's what happens: When the handler loads, it passes control to the
ProcessRequest method, along with a reference to the current HttpContext.
So the first thing I'm doing here is using the context to get the Request.Browser
object, and appending some of the interesting tidbits to my StringBuilder
which is basically designed just to create a CSV delimited text file. In
production, you would write the information to one or more database tables.
After I've assembled all the various pieces of info on the visitor that
I want, I write them to a log file. Finally, I simply construct the path
to the requested image and just Response.WriteFile it out to the browser!
You can use this for affitliate - tracking programs and things like that.
If somebody has an image tag on their page that has querystring items such
as "affiliateId=1023&customerId=213409", your handlier can be
instructed to dutifully capture and record the number of times that image
was viewed
or how many times it was clicked, by whom, for which affiliate, and when
it happened.
And just so you can see it all in action, here's a link to a test page (view
the source of it to see it's code) that will let you choose one of two
images and see your own statistical information that it has captured as
in the code above:
Visitor Information Test Page
| |
| | Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform. |
|