RESTian ratings images
2007-11-12 @ 17:49#
i needed to implement a feature that displayed a set of 'stars' representing the computed customer rating of an image. the database is returning the rating value and i have a fixed set of images (0-5 stars, incremented by .5). all i needed was a clean way to get the proper image from the server.
i implemented a simple .ashx file for ASP.NET that checked for query params and returned the proper image. i return 4XX when needed and even 5XX in the case of really bad stuff. otherwise, i return a clean, cache-able image/png content type every time.
below is the entire code for the handler:
<%@ WebHandler Language="C#" Class="RatingImage" %>
using System;
using System.Web;
using System.IO;
// returns an image that corresponds to the rating passed in
// <img src="ratingimage.ashx?rating=4.5" />
public class RatingImage : IHttpHandler
{
const double expires = 60 * 60 * 24 * 30; // 30 days
const string cache_control_fmt = "public,max-age={0}";
const string expires_fmt = "{0:ddd dd MMM yyyy HH:mm:ss} GMT";
const string default_location = "/images/ratings-stars";
const string url_fmt = "/content/{0}/{1}";
Utility util = new Utility();
public void ProcessRequest(HttpContext context)
{
try
{
context.Response.ContentType = "image/png";
context.Response.StatusCode = 200;
context.Response.TransmitFile(string.Format(url_fmt, GetLocation(context),GetFile(context)));
if (expires != 0)
{
context.Response.AddHeader("Cache-Control", string.Format(cache_control_fmt, expires));
context.Response.AddHeader("Expires", string.Format(expires_fmt, System.DateTime.UtcNow.AddSeconds(expires)));
}
}
catch (HttpException hex)
{
context.Response.ContentType = "text/plain";
context.Response.StatusCode = hex.GetHttpCode();
context.Response.StatusDescription = hex.Message;
context.Response.Write(hex.Message);
}
catch (Exception ex)
{
context.Response.ContentType = "text/plain";
context.Response.StatusCode = 500;
context.Response.StatusDescription = ex.Message;
context.Response.Write(ex.Message);
}
}
public bool IsReusable
{
get
{
return false;
}
}
string GetFile(HttpContext context)
{
double x = Convert.ToDouble(GetRating(context));
string rtn = string.Empty;
if (x < .3)
return "stars00.gif";
if (x < .7)
return "stars05.gif";
if (x < 1.3)
return "stars10.gif";
if (x < 1.7)
return "stars15.gif";
if (x < 2.3)
return "stars20.gif";
if (x < 2.7)
return "stars25.gif";
if (x < 3.3)
return "stars30.gif";
if (x < 3.7)
return "stars35.gif";
if (x < 4.3)
return "stars40.gif";
if (x < 4.7)
return "stars45.gif";
return "stars50.gif";
}
string GetRating(HttpContext context)
{
if (context.Request.QueryString["rating"] != null)
return context.Request.QueryString["rating"];
else
throw new HttpException(400, "Missing Rating");
}
string GetLocation(HttpContext context)
{
if (context.Request.QueryString["location"] != null)
return context.Request.QueryString["location"];
else
return default_location;
}
}