Situations when IHttpHandler GetHttpHandler does not fire
Asked Answered
H

1

1

I have a project that requires changes in MVC's default routing behavior for image http requests.

For example, this sample from RouteConfig.cs

Route ImagesRoute = new Route("{controller}/{folderName}/{fileName}", new ImageRouteHandler());
string regexWindowsFilePattern = @"^([^\x00-\x1f\\?/%*:|" + "\"" + @"<>]+)\.(?:jpeg|jpg|tiff|gif|png)";

ImagesRoute.Constraints = new RouteValueDictionary { { "fileName", regexWindowsFilePattern } };
routes.Add(ImagesRoute);

should reroute

http://localhost/home/contents/image.jpg

to path on disk (c:\cache\[folderName][fileName]). The "rerouting" in my case is just writing the correct http response based on request. In one project (lets call it the "Test" project) this code triggers normal behavior: the GetHttpHandler method of ImageRouteHandler class gets hit and the image appears in browser, however in other project with identical code for RouteConfig.cs and ImageRouteHandler inserted GetHttpHandler simply does not fire which results in 404 NOT FOUND http error. This other project (the "destination" project) has almost the same configuration (I have checked the relevant differences) and have been run on the same IIS express server. Creating new project and populating in with contents of destination and test project results in normal behavior (i.e. the image is displayed in browser). Any clue on what the solution might be?

update_1:
I forgot to mention that the action is not used deliberately. I have an html file that I must include into partial view which will render html file body. I don't have control over how this file is created but I have a defined structure: html file with name [htmlFileName] and a resource folder name with name [htmlFileName].files. When I request a specific URL (say localhost/[Controller]/[Action]) the references to resources in HTML markup result in incorrect URLs (http:// localhost/[Controller]/[folderName]/[fileName]) so I need to rewrite these URLs so that the browser's http image requests are prorerly answered. Thats why I think this custom handler is needed.

using System;
using System.Net;
using System.Web;
using System.IO;
using System.Web.Routing;

namespace MyProject.WebUI.Interface.Utility
{
    public class ImageRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            string fileName = requestContext.RouteData.Values["fileName"] as string;
            string folderName = requestContext.RouteData.Values["folderName"] as string;

            if (string.IsNullOrEmpty(fileName))
            {
                // return a 404 NOT FOUND HttpHandler here
                requestContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
            }
            else
            {
                requestContext.HttpContext.Response.Clear();

                if (requestContext.HttpContext.Request.Url != null)
                {
                    requestContext.HttpContext.Response.ContentType =
                        GetContentType(requestContext.HttpContext.Request.Url.ToString());
                }
                else
                {
                    requestContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    requestContext.HttpContext.Response.End();
                }

                // find physical path to image here.  
                string filepath = @"c:\Cache" + @"\" + folderName + @"\" + fileName;

                /*If file exists send the response, otherwise set HTTP 404 NOT FOUND status code for response.*/
                if (File.Exists(filepath))
                {
                    requestContext.HttpContext.Response.WriteFile(filepath);
                    requestContext.HttpContext.Response.End();
                }
                else
                {
                    requestContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
                    requestContext.HttpContext.Response.End();
                }


            }
            return null;
        }


        private static string GetContentType(String path)
        {
            switch (Path.GetExtension(path))
            {
                case ".bmp": return "Image/bmp";
                case ".gif": return "Image/gif";
                case ".jpg": return "Image/jpeg";
                case ".jpeg": return "Image/jpg";
                case ".png": return "Image/png";
                default: break;
            }
            return "";
        }
    }
}
Halfway answered 18/12, 2012 at 15:47 Comment(1)
I have edited your title. Please see, "Should questions include “tags” in their titles?", where the consensus is "no, they should not".Mudcat
H
3

It appears to be that in one project there is a "modules" element in Web.config

<modules runAllManagedModulesForAllRequests="true" />

which allowed routing module to work properly with image requests. It is placed in Web.config by default and for some reason there is no such xml element in the other project. Though this is a solution for a problem I found a better one:

<modules>
  <remove name="UrlRoutingModule-4.0" />
  <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>

This enables only one (instead of all) managed module for any type of requests. After adding these xml elements to Web.config the GetHttpHandler of ImageRouteHandler gets hit as intended.

Halfway answered 19/12, 2012 at 11:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.