The .ashx extension – Writing your own HttpHandler

Have you noticed how Sitecore serves images using an .ashx extension? A .ashx file is a HttpHandler. A HttpHandler is kind of a lightweight aspx page, as the HttpHandler only deals with the HttpContext - for example there is no page information. This makes it a great tool for implementing providers for images, xml, rss feeds or other stuff that can be generated using parameters only.

The .ashx file implements the System.Web.IHttpHandler (or the System.Web.IHttpAcynchandler for async calls – I’ll only show the first one), which contains only 1 property (IsReusable) and one function (ProcessRequest()). The ProcessRequest() function have one parameter only, the HttpContext to read and write data to.

My Visual Studio have no default creation of .ashx extensions, so I’ll have to make one manually. I create a new file with the .ashx extension and adds the following line:

<% @ WebHandler language="C#" class="MyNamespace.MyClass" codebehind="mycodebehind.cs" %>

Then I have to create a mycodebehind.cs file and add a class called MyNamespace.MyClass. This class should implement the IHttpHandler interface:

using System.Web;

namespace MyNamespace
{
  public class MyClass : IHttpHandler
  {
    public bool IsReusable
    {
      get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
      // Here goes all of my code
    }
  }
}

Now my ProcessRequest can serve anything I like. I can reteieve paramaters from the Request and write to the Response:

public void ProcessRequest(HttpContext context)
{
  string parameter = context.Request.Params["myparameter"];
  context.Response.Write(parameter);
}

Or I can output a file (like Sitecore does):

public void ProcessRequest(HttpContext context)
{
  System.IO.MemoryStream ms = new System.IO.MemoryStream();
  Image image = SomeFunctionGeneratingAnImageForme();
  image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
  context.Response.ContentType = "image/jpeg";
  context.Response.OutputStream.Write(ms.GetBuffer(), 0, Convert.ToInt32(ms.Length));
}

I’ve noticed how Sitecore registers theit HttpHandlers in the web.config. You really don’t have to do that (even if Microsoft says so). You can call them directly. But if you wish to do so, you should read this article on how to register a HttpHandler.

Media Library file names. Tired of guids?

Have you noticed that when uploading files to the media library, sometimes the resulting file name is a guid? If I upload an image, say Brian.jpg, I need to write ~/media/9B62BB56FD6040FAA56C6DB1D8A0BDE6.ashx in order to acces it from the front end.

And why is this a problem? Some search crawlers use the file name as title when the item is indexed. The Ankiro crawler can be configured to use the meta title (found in PDF or Word documents) or the file name as index title. Seeing a search result list with the file name 9B62BB56FD6040FAA56C6DB1D8A0BDE6 is not very explanatory for the end users.

Can this be configured? Well of course. This is Sitecore we are talking about.

The web.config contains loads of settings controlling the Media Library. Set the Media.UseItemPaths to true and your uploaded files will answer to the original file name so my Brian.jpg can be accessed at ~/media/Folder/Brian.ashx instead.

<!--  MEDIA - USE ITEM PATHS FOR URLS
      This setting controls if item paths are used for constructing media URLs.
      If false, short ids will be used.
      Default value: true
-->
<setting name="Media.UseItemPaths" value="true" />

Sitecore 5.3 and ImageURI

If you assign the path of a media item to a Image.ImageUrl in code behind it will not find the image unless you prefix the path with a /, see the example code below:

// ensure that the url has a / before any ~
string spotItemURL = myImageField.Path;
if(spotItemURL.StartsWith("~"))
  spotItemURL = /" + spotItemURL;

If you do not make the above check the image will be renders in HTML as follows:

<img src="~/media/60DAF58AD915497A893315F10CCEBD94.ashx" />

And both IE & Firefox cannot find the image, if you prefix the url with a /, using the code above the output will be as follows:

<img src="/~/media/60DAF58AD915497A893315F10CCEBD94.ashx">

Follow

Get every new post delivered to your Inbox.

Join 92 other followers