Introduction
Here, I am going to explain how one can implement HttpHandler
in ASP.NET MVC5. Similar to how we use it in ASP.NET webform.
Background
Coming from ASP.NET webform background, I was curious to know how we can implement HttpHandler
if we needed one. It was really hard to find any decent complete article. With my limited experience, I can say that one rarely uses HttpHandler
in MVC. But there may arise a corner case where you might need to use one.
Using the Code
Implement IHttpHandler
Let us start by adding a Class
in the root (can be added to any place inside project) of our MVC 5 project and name it MyHttpHandler
. To have a custom implementation of handler in ASP.NET, we have to Inherit IHttpHandler
and implement the ProcessRequest()
. Take a look at the below code:
public class MyHttpHandler : IHttpHandler
{
RequestContext _requestContext { get; set; }
public MyHttpHandler(RequestContext requestContext)
{
_requestContext = requestContext;
}
public bool IsReusable
{
get
{
return true;
}
}
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Response.Write("My custom handler response.");
}
}
In the above code, you can see that we have inherited IHttpHandler
and implemented its method ProcessRequest()
. The default constructor of MyHttpHandler
is not required to be overridden as show above and it’s been added only for further flexibility in future.
Implement IRouteHandler
Now, we need to inherit IRouteHandler
and implement GetHttpHandler()
method. Start by creating another class called MyRouteHandler
that inherits IRouteHandler
, you can create it anywhere and implement GetHttpHandler()
as shown below:
public class MyRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return new MyHttpHandler(requestContext);
}
}
In the above code, MyHttpHandler()
constructor accepts the parameter requestContext
only because we have implemented it that way, you can choose to make the necessary modification to remove it.
Registering RouteHandler
We have completed creating custom handler and RouteHandler
that implements it. But the ASP.NET MVC pipeline is not aware of this and when to call it. So we need to register it and provide the constraint that will trigger MyRouteHandler
. For that, add the following code in RouteConfig class that is in App_Start folder, immediately below your routes.IgnoreRoute("{resource}.axd/{*pathInfo}
.
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
Route NewRoute = new Route("{folder}/{type}", new MyRouteHandler());
NewRoute.Defaults = null;
NewRoute.Constraints = new RouteValueDictionary { { "folder", "MyFolder" } }
routes.Add("HandlerRoute", NewRoute);
Any request that has strictly this "{folder}/{type}" format will be routed to your custom handler (MyRouteHandler
). Example: localhost:51496/MyFolder/ImageName
Now what if you need special handling for a particular static file. Example: .png, .jpg, .pdf.
Using Handler for Static File
The above code runs good for any request that comes with "localhost:51496/MyFolder/ImageName" format, the MyRouteHandler
will be called. What if you want to handle static file of a certain type? The IIS will serve static file directly without passing the request to MVC. We have to explicitly mention to route the request to MVC if static file is requested.
We need to add a below entry in web.config file. Here, we are handling .png file.
<system.webServer>
<handlers>
<add name="StaticFileHandler" path="*.png"
verb="GET" type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Now request with localhost:51496/MyFolder/ImageName.png will be handled by our MyRouteHandler
and not by IIS.
Real world requirements might be more complex than the example mentioned here, hope this gives you a fairly good idea where to start and how to approach the problem.
Thanks for reading!
History
- 26th July, 2019: Initial version