Question

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 "";
        }
    }
}
Était-ce utile?

La solution

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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top