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浏览器就很稳定,能中断,也能按约束正常路由匹配。