Introduction
I often map html extention to the asp.net dll in order to use url rewritter with .html extentions. Recently, in the new version of www.nouvelair.ca, we renamed all urls to end with .html. This works great, but failed when we used FCK Editor. Static html files would not get serve because we mapped the html extension to the .NET Framework. We can we do to to use .html extension with our rewritter but still want to use IIS behavior with static html files.
Analysis
I thought that this could be resolve with a simple HTTP handler. We would map urls of static files in our rewriter to this handler that would read the static file and serve it, just as IIS would do.
Implementation
This is how I coded the class. Note that this may not be bullet proof. I only tested it once and I am sure that the logic behind IIS is more complicated that this. If you find errors or think of possible improvements, let me know.
Imports System.Web
Imports System.Web.Services
' Author: Nicolas Brassard
' For: Solutions Nitriques inc. http://www.nitriques.com
' Date Created: April 18, 2009
' Last Modified: April 18, 2009
' License: CPOL (http://www.codeproject.com/info/cpol10.aspx)
' Files: ISAPIDotNetHandler.ashx
' ISAPIDotNetHandler.ashx.vb
' Class: ISAPIDotNetHandler
' Description: Fake ISAPI handler to serve static files.
' Usefull when you want to serve static file that has a rewrited extention.
' Example: It often map html extention to the asp.net dll in order to use url rewritter with .html.
' If you want to still serve static html file, add a rewritter rule to redirect html files to this handler
Public Class ISAPIDotNetHandler
Implements System.Web.IHttpHandler
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
' Since we are doing the job IIS normally does with html files,
' we set the content type to match html.
' You may want to customize this with your own logic, if you want to serve
' txt or xml or any other text file
context.Response.ContentType = "text/html"
' We begin a try here. Any error that occurs will result in a 404 Page Not Found error.
' We replicate the behavior of IIS when it doesn't find the correspoding file.
Try
' Declare a local variable containing the value of the query string
Dim uri As String = context.Request("fileUri")
' If the value in the query string is null,
' throw an error to generate a 404
If String.IsNullOrEmpty(uri) Then
Throw New ApplicationException("No fileUri")
End If
' If the value in the query string doesn't end with .html, then block the acces
' This is a HUGE security hole since it could permit full read access to .aspx, .config, etc.
If Not uri.ToLower.EndsWith(".html") Then
' throw an error to generate a 404
Throw New ApplicationException("Extention not allowed")
End If
' Map the file on the server.
' If the file doesn't exists on the server, it will throw an exception and generate a 404.
Dim fullPath As String = context.Server.MapPath(uri)
' Read the actual file
Dim stream As IO.StreamReader = FileIO.FileSystem.OpenTextFileReader(fullPath)
' Write the file into the response
context.Response.Output.Write(stream.ReadToEnd)
' Close and Dipose the stream
stream.Close()
stream.Dispose()
stream = Nothing
Catch ex As Exception
' Set the Status Code of the response
context.Response.StatusCode = 404 'Page not found
' For testing and bebugging only ! This may cause a security leak
' context.Response.Output.Write(ex.Message)
Finally
' In all cases, flush and end the response
context.Response.Flush()
context.Response.End()
End Try
End Sub
' Automaticly generated by Visual Studio
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Conclusion
As you see, with our static files map to this handler using query string (ex.: /ISAPIDotNetHandler.ashx?fileUri=index.html) you will have the same behavior as if you ask for the uri /index.html.
Finally, test this only in IIS with the html extension map to aspnet_isapi.dll. Url rewritting will work in Casini (Internal Web Server shipped with Visual Studio) but it’s not the same as with IIS since EVERY request is handle by .NET.
Versions
First release