首页 > 代码库 > 对磁盘文件的请求进行路由

对磁盘文件的请求进行路由

url中如果有对静态文件的请求,也可以对它进行路由。例如,图片、静态html文件、JavaScript库等。

在前面例子的解决方案中,在Content文件夹中创建一个叫做“StaticContent.html”的文件。

<html>
<head>
    <title>Static HTML Content</title>
</head>
<body>
this is the static html file (~/Content/StaticContent.html)
<h2>你现在使用的不是Chrome浏览器,请使用Chrome浏览器访问</h2>
</body>
</html>

 默认情况下,路由系统会先考察一个url是否直接匹配磁盘文件。如果有匹配,就直接访问到这个磁盘文件,默认就不使用路由,包括路由中的约束都不对此访问起作用。例如,对上面的文件,在默认情况下,在任一浏览器中直接给出url:

"~/Content/ContentStatic.html"

就可以直接访问到。

 

如果希望在检查磁盘文件之前,先进行路由匹配,可以将RouteExistingFils属性设置为true,例如:

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.RouteExistingFiles = true;
            routes.MapRoute("DiskFile", "Content/StaticContent.html",
                new { Controller = "Account", Action = "LogOn" },
                new { customConstraint = new UserAgentConstraint("Chrome") });
            
            routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}",
                new { Controller = "Home", Action = "Index", id = UrlParameter.Optional },
                new { Controller="^H.*", Action="^Index$|^About$",
                httpMethod = new HttpMethodConstraint("GET")},
                new[] { "_11_3URLTestDemo.Controllers" });
        }

上面的new { customConstraint = new UserAgentConstraint("Chrome") }使用了自定义的一个类UserAgentConstraint来生成一个实例,通过判断客户端浏览器发出请求时,传递过来的状态字符串中是否包含特定子串,来限定指定的浏览器。客户端浏览器的状态字符串是通过属性httpContext.Request.UserAgent传递过来的。因此,在当前项目中11-3URLTestDemo中新建一个名为“Infrastructure”的文件夹,在此文件夹中添加一个类库文件UserAgentConstraint.cs,内容如下:

namespace _11_3URLTestDemo.Infrastructure
{
    public class UserAgentConstraint:IRouteConstraint
    {
        private string requiredUserAgent;

        public UserAgentConstraint(string agentParam)
        {
            requiredUserAgent = agentParam;
        }

        public bool Match(HttpContextBase httpContext, Route route, string parameterName,
            RouteValueDictionary values, RouteDirection routeDirection)
        {
            return httpContext.Request.UserAgent != null &&
                httpContext.Request.UserAgent.Contains(requiredUserAgent);
        }
    }
}

当然,前面在Global.asax中使用该类来生成实例时,就需要using _11_3URLTestDemo.Infrastructure;
在Global.asax的RegisterRoutes中,首先设置

routes.RouteExistingFiles = true;

表示对磁盘文件的url请求要先进行路由匹配,路由不匹配时才对该磁盘文件直接访问。

接下来设置了对该磁盘文件的路由:

            routes.MapRoute("DiskFile", "Content/StaticContent.html",
                new { Controller = "Account", Action = "LogOn" },
                new { customConstraint = new UserAgentConstraint("Chrome") });

如果有url请求"~/Content/StaticContent.html",就会路由到Controller为Account,Action为LogOn的方法上进行执行,而且后面还有一个约束,就是客户端浏览器传递过来的状态字符串中要包含Chrome,也就是限定了只有客户端是使用的Chrome浏览器时,才做此路由,否则,就直接访问Content/StaticContent.html

通过这样的设置,就可以限定在对某一url请求时,根据客户端使用的浏览器不同,来做不同的处理。

在本例中,对于"~/Content/StaticContent.html"的请求,如果用户用的Chrome浏览器,则匹配路由,执行AccountController里的LogOn方法,如果用户用的是其他浏览器(比如ie),那么就直接给出对StaticContent.html文件的访问。

Chrome的 httpContext.Request.UserAgent "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36" string

ie10的httpContext.Request.UserAgent "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)" string

 

在实验过程中,上面的例子限定Chrome能够稳定执行。

但是在限定ie浏览器时,执行不稳定。例如,

routes.MapRoute("DiskFile", "Content/StaticContent.html",
          new { Controller = "Account", Action = "LogOn" },
          new { customConstraint = new UserAgentConstraint("MSIE") });

企图限定客户端使用ie浏览器才匹配路由,否则直接给出对StaticContent.html的访问。实验时采用的ie10,可以看到上面给出的状态字符串,直接限定字符给IE是不行,给MSIE,但在执行过程中在UserAgentConstraint.cs的:

return httpContext.Request.UserAgent != null &&
                httpContext.Request.UserAgent.Contains(requiredUserAgent);

处设置断点,有时能中断,有时不能中断。路由也是有时匹配,有时不匹配,目前没有找到引起这个问题的原因。使用Chrome浏览器就很稳定,能中断,也能按约束正常路由匹配。