1

我有一个项目需要更改 MVC 对图像 http 请求的默认路由行为。

例如,来自 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);

应该重新路由

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

到磁盘上的路径 (c:\cache\[folderName][fileName])。在我的情况下,“重新路由”只是根据请求编写正确的 http 响应。在一个项目(让我们称之为“测试”项目)中,这段代码触发了正常行为:ImageRouteHandler 类的 GetHttpHandler 方法被命中并且图像出现在浏览器中,但是在其他项目中,RouteConfig.cs 和 ImageRouteHandler 的代码相同,只是简单地插入了 GetHttpHandler不会触发,导致 404 NOT FOUND http 错误。这个另一个项目(“目标”项目)具有几乎相同的配置(我已经检查了相关差异)并且已经在同一个 IIS express 服务器上运行。创建新项目并使用目标和测试项目的内容填充会导致正常行为(即图像显示在浏览器中)。

update_1:
我忘了说这个动作不是故意使用的。我有一个必须包含在部分视图中的 html 文件,该文件将呈现 html 文件正文。我无法控制如何创建此文件,但我有一个定义的结构:名称为 [htmlFileName] 的 html 文件和名称为 [htmlFileName].files 的资源文件夹名称。当我请求一个特定的 URL(比如 localhost/[Controller]/[Action])时,HTML 标记中对资源的引用会导致 URL 不正确(http://localhost/[Controller]/[folderName]/[fileName])所以我需要重写这些 URL,以便正确响应浏览器的 http 图像请求。这就是为什么我认为需要这个自定义处理程序。

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 "";
        }
    }
}
4

1 回答 1

3

似乎在一个项目中,Web.config 中有一个“模块”元素

<modules runAllManagedModulesForAllRequests="true" />

这允许路由模块正常处理图像请求。它默认放置在 Web.config 中,由于某种原因,其他项目中没有这样的 xml 元素。虽然这是一个问题的解决方案,但我找到了一个更好的解决方案:

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

对于任何类型的请求,这仅启用一个(而不是全部)托管模块。将这些 xml 元素添加到 Web.config 后,ImageRouteHandler 的 GetHttpHandler 会按预期命中。

于 2012-12-19T11:56:51.803 回答