As you all know, Sitecore has customized the whole ASP.NET framework a little for own proposes. Sometimes this does mean that you have to take a little more actions to get some stuff done. Today I’m going to show you how we can create a cool .ashx. I’m going to generate some extreme cool circles
.
You properly can do this without following all the steps below and do it how it should be done, but you won’t have a fully initialized Sitecore-context in that case.
First I’ve to think about the url I want to access the httpHandler.
Note: Like Sitecore does with its media and icons, I do recommend to start your url with a tilde(~). The ASP.NET-engine does recognize the tilde as the root, so both the following urls will give you the same page:
http://yoursite.ext/~/media/mypicture.ashx
http://yoursite.ext/something/~/media/mypicture.ashx
My url for generating those cool circle should become:
http://localhost/~/generation/images/cirkel.ashx
Then I’ve to decide how it should be rewritten internal. Media-urls will be rewritten to sitecore_media.ashx inside Sitecore, Icons become sitecore_icons.ashx, etc. I’ll use ‘custom_imagegen.ashx’.
Now we’ve to configure this. First we setup the nice url. Therefor we’ve to open the web.config. Then you’ve to search for the node ‘customHandlers’ under the ‘sitecore’-node. Then add another customHandler like I’ve done below:
<customHandlers>
<handler trigger=“~/media/“ handler=“sitecore_media.ashx“ />
<handler trigger=“~/api/“ handler=“sitecore_api.ashx“ />
<handler trigger=“~/rest/“ handler=“sitecore_rest.ashx“ />
<handler trigger=“~/xaml/“ handler=“sitecore_xaml.ashx“ />
<handler trigger=“~/icon/“ handler=“sitecore_icon.ashx“ />
<handler trigger=“~/generation/images/“ handler=“custom_imagegen.ashx“ />
</customHandlers>
Then the we’ve to configure the httpHandler under the ‘system.web’-node:
<httpHandlers>
<add verb=“*“ path=“sitecore_media.ashx“ type=“Sitecore.Resources.Media.MediaRequestHandler, Sitecore.Kernel“ />
<add verb=“*“ path=“sitecore_rest.ashx“ type=“Sitecore.Web.UI.XamlSharp.Ajax.RestPageHandlerFactory, Sitecore.Kernel“ />
<add verb=“*“ path=“sitecore_xaml.ashx“ type=“Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel“ />
<add verb=“*“ path=“sitecore_icon.ashx“ type=“Sitecore.Resources.IconRequestHandler, Sitecore.Kernel“ />
<add verb=“*“ path=“custom_imagegen.ashx“ type=“Sitecore.TestSite.ImageGenerator, Sitecore.TestSite“ />
</httpHandlers>
As you can see, I’ve configured a class to the handler. Make sure the class implements System.Web.IHttpHandler and its members.
I’ve created the following demonstration class to test if my configuration works:
1 public class ImageGenerator : IHttpHandler
2 {
3 #region IHttpHandler Members
4
5 public bool IsReusable
6 {
7 get { return true; }
8 }
9
10 public void ProcessRequest(HttpContext context)
11 {
12 context.Response.Write(context.Request.RawUrl);
13 }
14
15 #endregion
16 }
After building the solution it becomes time to test my implementation. Let’s try: http://localhost/~/generation/images/cirkel.ashx. And as expected, the page returns:
/~/generation/images/cirkel.ashx
Note: Make sure you set ‘IsReusable’ to true as it indicates weather the system can reuse the instance of the class for another request.
Alright, so that seems to work! Now it’s time to create a cool circle generator…
1 public class ImageGenerator2 : IHttpHandler
2 {
3 #region Field(-s)
4 public int DefaultAlpha
5 {
6 get
7 {
8 return 80;
9 }
10 }
11 public Color DefaultColor
12 {
13 get
14 {
15 return Color.Red;
16 }
17 }
18 public Size DefaultSize
19 {
20 get
21 {
22 return new Size(200, 200);
23 }
24 }
25 public int QueryStringAlpha
26 {
27 get
28 {
29 return GetIntFromQueryString(“alpha”, DefaultAlpha, 255);
30 }
31 }
32
33 public Color QueryStringColor
34 {
35 get
36 {
37 return Color.FromArgb(GetIntFromQueryString(“c”, DefaultColor.ToArgb(), 2000));
38 }
39 }
40 public Size QueryStringSize
41 {
42 get
43 {
44 return new Size(GetIntFromQueryString(“w”, DefaultSize.Width, 2000), GetIntFromQueryString(“h”, DefaultSize.Height, 2000));
45 }
46 }
47 #endregion
48
49 #region IHttpHandler Members
50 public bool IsReusable
51 {
52 get { return true; }
53 }
54
55 public void ProcessRequest(HttpContext context)
56 {
57 WriteResponseHeader(context);
58
59 using (Bitmap myImg = new Bitmap(QueryStringSize.Width, QueryStringSize.Height))
60 {
61 DrawOnBitmap(myImg);
62
63 MemoryStream ms = new MemoryStream();
64 myImg.Save(ms, ImageFormat.Png);
65 ms.WriteTo(context.Response.OutputStream);
66 }
67 }
68 #endregion
69
70 #region Protected Members
71 protected void WriteResponseHeader(HttpContext context)
72 {
73 context.Response.ClearHeaders();
74 context.Response.AddHeader(“Content-Type”, “image/png”);
75 context.Response.AddHeader(“Content-Transfer-Encoding”, “binary”);
76 context.Response.CacheControl = “public”;
77 }
78
79 protected void DrawOnBitmap(Bitmap image)
80 {
81 Rectangle rect = new Rectangle(Point.Empty, QueryStringSize);
82
83 //Hack to make sure the Ellipse fits in my Image
84 rect.Width–;
85 rect.Height–;
86
87 using (Graphics g = Graphics.FromImage(image))
88 {
89 g.SmoothingMode = SmoothingMode.AntiAlias;
90 Color c = Color.FromArgb(QueryStringAlpha, QueryStringColor.R, QueryStringColor.G, QueryStringColor.B);
91
92 g.DrawEllipse(new Pen(c), rect);
93 g.FillEllipse(new SolidBrush(c), rect);
94 }
95 }
96 #endregion
97
98 #region Private Static Helper(-s)
99 private static int GetIntFromQueryString(string key, int defaultValue, int maxValue)
100 {
101 string qsValue = HttpContext.Current.Request.QueryString[key];
102 int resultValue;
103
104 if (!string.IsNullOrEmpty(qsValue) && int.TryParse(qsValue, out resultValue) && resultValue <= maxValue)
105 {
106 return resultValue;
107 }
108 return defaultValue;
109 }
110 #endregion
111 }
Playing around with the options described above showed me that /~/media/ is hardcoded in a lot of Sitecore-code. That’s a pity. Hopefully one of the developers will pick this up and fix it in the next build.

[...] http://sitecore.alexiasoft.nl/2007/09/13/adding-your-own-httphandler-to-sitecore-53/ http://www.fishofprey.com/2010/12/sending-sitecore-mediastream-through.html [...]