In 7 write similar code, but place inside different section:
<system.WebServer>
<handlers>
<add verb="*" path="*.jpg" type="ImageHandler" />
<handlers>
<system.WebServer>
IIS only passes requests for specific file types to ASP.NET, for other types it passes the file from file system directly to browser.
As with web.config the process differs slightly between IIS 6 and 7.
To configure IIS 7:
~~ Using The .ashx Extension
.ashx reserved for custom HTTP handlers - extension already registered with system.
For example generate class that implement IHttpHandler, perhaps basing it behaviour on query string contents.
Add a file to site with .ashx extension containing WebHandler directive to point to the class, e.g.
<%@ WebHandler Language="C#" Class="ImageHandlerQs" %>;
Can then call:
http://localhost:56560/lessons/MyImageHandler.ashx?jellyfish
Allows request to execute on non-ASP.NET thread, allows ASP.NET to continue processing requests =>; responsive site.
Implementation can be tricky - use performance tools to verify performance under heavy load. Sometime overhead introduced by async programming can offset benefits.
ASP.NET will place handler on a separate thread.
The thread that would normally run synchronous HTTP handlers is then placed back into thread pool to handle additional user requests - reduces chance that limited set of ASP.NET threads will become exhausted.
Handler derives from IHttpAsyncHandler interface, override IsReusable and BeginProcessRequest.
public class AsyncImageHandler: IHttpAsyncHandler
{
public bool IsResuable { get { return false; } }
public IAsyncResult BegineProcessRequest(HttpContext context, AsyncCallback cb, object extra)
{
ImageAsyncOp imageOp = new ImageAsyncOp(cb, context, extra);
imageOp.StartAsync();
}
public void EndProcessRequest(IAsyncResult res) {};
public void ProcessRequest(HttpContext context) {};
}
The class performing the operation derives from IAsyncResult. In this example the StartAsync method will queue a work item. This work item will cal the AsyncCallback once processing is complete.
class ImageAsyncOp : IAsyncResult
{
AsyncCallback _cb;
public ImageAsyncOp(AsyncCallback cb, HttpContext con, object state)
{
_callback = cb;
...
}
public void StartAsync()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncOperation), null);
}
public void StartAsyncOperation(object workItemState)
{
...
_callback(this);
}
}
Also provide callback method that gets called when asynchronous operation completes.
Any clean up that is required should be placed in EndProcessRequest.
No IIS registration required, just run the web page.
In @Page directive add Async=true:
<@Page Language="C#" Async="true" AutoEventWireup="true" %>;
In code behind file create methods called when async processing starts and ends:
protected IAsyncResult begin(object sender, EventArgs e, AsyncCallback cb, object extra)
{
ImageAsyncOp io = new ImageAsyncOp(cb, this.Context, extra);
}
protected void End(IAsyncResult res) {};
Inside the Page_Load invoke the asynchronous operation:
AddOnPreRenderCompleteAsync(new BeginEventHandler(gein), new EndEventHandler(end));
Code executed every time page requested or response sent, similar to old ISAP filters except it is executed within CLR.
Create by deriving from IHttpModule interface.
Can write as assembly shared across multiple web apps, or just as a class in App_Code directory.
ASP.NECreates instance of HttpApplication when you app starts. This class finds any registered modules and creates instances of them.
Inside the Init method of the HTTP module indicate which application events the module handles.
public class LoggingModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += (new EventHandler(this.App_BeginReq));
}
public void App_BeginReq(Object source, EventArgs e)
{
...
}
}
Register HTTP modules via web.config:
<httpModules>
<add name="LoggingModule" type="LoggingModule" />
<httpModules>
or
<modules>
<add name="LoggingModule" type="LoggingModule" />;
<modules>
Global.asax can be used to register code for application events.
Do this by adding code to Application_BeginRequest, Application_LogRequest, etc.
This code runs just like HTTP module, but does not need registration.
Typically create HTTP Module to encapsulate complex code or share code across websites.
For simple needs the Global.asax is a better choice.