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; } }