Friday, 6 June 2008

First IIS 7 module

Hi,

To see what I can do with the example they gave here:

http://blogs.iis.net/rickjames/archive/2007/02/26/iis-7-hello-world-module-walkthrough.aspx

I want to see if I can create an IIS 7 module for JPEG files, to allow image flipping, then maybe some other things later on, eg:
http://mywebsite.com/picture.jpg?flip=true

What I will need to establish (I'm guessing) is:
* How we can read the GET string into the module
* How we can send the headers and mime types back in the response
* How to establish what directory to stream the image from
* How to load the .NET image libraries


Then download a starter pack for IIS 7 modules (should give me a head start)
http://www.iis.net/downloads/default.aspx?tabid=34&g=6&i=1302

This contains a vsi file, which (assuming you have Visual Studio installed), adds a template for a IIS 7 module.

Opening up the template it explains where to start:

A managed module class derives from the System.Web.IHttpHandler interface, and implements the following methods:

Init. This method is called when the module instance is initialized. It typically performs any instance-level initialization (such as reading configuration), and registers one or more of the module's methods for the desired request processing events.
Dispose. This method is called when the module instance is disposed. It typically does no work, unless the module needs to clean up any un-managed resources, or wants to do an early cleanup of its state before it is garbage collected.
ProcessRequest:
IsReusable:
Now for the development work

1. Create a project using the IIS7 Module template
2. Change the namespace and class names
3. Add a project reference for System. Drawing so that we have some imaging tools to play with.


And the code:

Firstly, setup our includes.


using System;
using System.Collections.Generic;
using System.Text;
using System.Web;

// Extra libs for this module
using System.IO;
using System.Drawing;

Start our class, implementing the IHttpHandler Interface

namespace ashaw.modules.iis7
{
public class AntsIIS7ImageFilter : IHttpHandler
{
#region IHttpHandler implementation - key
public AntsIIS7ImageFilter() { }
public String ModuleName { get { return "AntsII7ImageFilter"; } }
public void Init(HttpApplication application) { }
public void Dispose() { }
public bool IsReusable { get { return false; } }
#endregion

#region the actual request processing.
public void ProcessRequest (HttpContext context )
{
// Get the physical path that the image will be stored in
string path = context.Request.PhysicalPath;

// Get the file path
string filePath = context.Request.FilePath;

if (!File.Exists(path))
{
context.Response.AppendToLog("Can't find file:"+path);
context.Response.StatusCode = 404; // file does not exist
return;
}
try
{
// Setup the headers so that it knows its an image
context.Response.Headers["Content-Type"] = "image/jpeg";

// Create an image class for use!
Image myImage = new Bitmap(path);

// Check for flips
if (!String.IsNullOrEmpty(context.Request.Params["flip"]))
{
// Choose what kind of flip to do.
switch (context.Request.Params["flip"].ToLower())
{
case "x":
myImage.RotateFlip(RotateFlipType.RotateNoneFlipX);
break;
case "xy":
myImage.RotateFlip(RotateFlipType.RotateNoneFlipXY);
break;
case "y":
myImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
break;
}
}

// write the image to the output stream.
myImage.Save( context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg ) ;

}
catch (Exception ex)
{
// Write a message in the IIS logs
context.Response.AppendToLog(ex.Message);

// Return an error to the client
context.Response.StatusCode = 500;
context.Response.Write(ex.Message + ex.StackTrace );
}
}

#endregion


Next step: Build the solution, which generates a DLL, then setup your web.config to look similar to this:


<configuration>
<system.webserver>
<handlers>
<add name="ants" path="*.jpg" verb="*" type="ashaw.modules.iis7.AntsIIS7ImageFilter" resourcetype="Unspecified" requireaccess="Script" precondition="integratedMode">
</add>
</handlers>
</system.webserver>
<configuration>


Create a /bin directory in your web application and copy across a jpg file to test with.

Then try:
yourapp.com/mypicture.jpg

















yourapp.com/mypicture.jpg?flip=x

















yourapp.com/mypicture.jpg?flip=xy

















Then give yourself a pat on the back!

It's not hard to see how to change this to work for png images, or detect what kind you're requesting, just change the image type for the Image.Save () and the Content-Type for the MIME header.

No comments: