I recently upgraded a site from Umbraco 7.2.8 to Umbraco 7.5.2 and whilst the upgrade process was relatively straight forward, I had an issue with an HttpHandler that worked in 7.2.8 but failed to fire in 7.5.2.
Why was the handler not firing since upgrade?
Let's look at the files and config settings for an HttpHandler in a .net solution and then reveal the answer and solution to this conundrum in Umbraco 7.5.2
The HttpHandler required, is intended to prevent users or indexers accessing files via a direct URL within the Umbraco Media folder structure.
The handler checks whether the accessing request is authenticated and if not throws them back to the root of the site, which in this case is the login page.
The whole site requires authentication and Umbraco deals beautifully with site pages via forms authentication protocols - however these do not secure access to assets such as pdf's, word doc's etc in the media folder.
The site in question resides on IIS 8
Step 1. Create the handler code in your App_Code folder (or your own handlers folder if you prefer). The code receives a request and throws the user over to site root if not logged in. If the user is logged in then the handler identifies the file type requested and then issues the file to the user.
using System; using System.IO; using System.Web; namespace yourNameSpace.App_Code { public class FileHandler : IHttpHandler { public FileHandler() { } bool IHttpHandler.IsReusable { get { return false; } } void IHttpHandler.ProcessRequest(HttpContext context) { switch (context.Request.HttpMethod) { case "GET": { // Is the user logged-in? if (!context.User.Identity.IsAuthenticated) { System.Web.HttpContext.Current.Response.Redirect("/"); return; } string requestedFile = context.Server.MapPath(context.Request.FilePath); SendContentTypeAndFile(context, requestedFile); break; } } } HttpContext SendContentTypeAndFile(HttpContext context, String strFile) { context.Response.ContentType = GetContentType(strFile); context.Response.TransmitFile(strFile); context.Response.End(); return context; } public string GetContentType(string filename) { // used to set the encoding for the reponse stream string res = null; FileInfo fileinfo = new FileInfo(filename); if (fileinfo.Exists) { switch (fileinfo.Extension.Remove(0, 1).ToLower()) { case "pdf": { res = "application/pdf"; break; } case "doc": { res = "application/msword"; break; } case "docx": { res = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; break; } case "xls": { res = "application/vnd.ms-excel"; break; } case "xlsx": { res = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; break; } case "mp3": { res = "audio/mpeg"; break; } } return res; } return null; } } }
Step 2. Add the handler directives to your web.config within the section marked up:
<add name="DOCX" path="*.docx" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="XLSX" path="*.xlsx" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="DOC" path="*.doc" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="XLS" path="*.xls" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="PDF" path="*.pdf" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="MP3" path="*.mp3" verb="*" type="yourNameSpace.App_Code.FileHandler" />
Step 3. Put a break point within your handler and hit F11! Now, if you experience the same problem I did then your code won't hit the handler when you request one of the asset types in question, i.e. a pdf or doc file. Why not?
The answer lies in the root of the /Media folder as upgraded by the Umbraco 7.5.2 pathway. A supplementary web.config file exists in this directory.
This supplementary file is overriding your handling intentions as defined in the root web.config file. We simply need to remove our handler directives from the root web.config and place in the /Media folder's web.config
Original /Media/web.config
<?xml version="1.0" encoding="UTF-8"?/> <configuration/> <system.webServer/> <handlers/> <clear //> <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" //> </handlers/> </system.webServer/> </configuration/>
Revised /media/web.config
<configuration> <system.webServer> <handlers> <clear /> <add name="DOCX" path="*.docx" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="XLSX" path="*.xlsx" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="DOC" path="*.doc" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="XLS" path="*.xls" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="PDF" path="*.pdf" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="MP3" path="*.mp3" verb="*" type="yourNameSpace.App_Code.FileHandler" /> <add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" /> </handlers> </system.webServer> </configuration>
Step 4. Hit F11 again and attempt to access a handled asset extension - hey presto! All is now functioning correctly.
Remember; we're Umbraco registered partners, get in touch and tell us how we can help you.