约束路由
上面我们有一个{id}用来捕获参数的,但是你也发现了它可以捕捉任何字符串等等,但是我们有时需要限制它,比如让它只能输入数字,那么我们就可以使用正则表达式去约束它。
如下修改RouteConfig.cs:
1 public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.MapRoute(
6 name: "Default",
7 url: "{controller}/{action}/{id}",
8 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
9 constraints: new{id = @"^\d*$"},
10 namespaces: new[] { "MvcStudy.Controllers" }
11 );
12 }
13 }
我们可以清楚的看到我们通过constraints参数将id参数约束为只能输入数字,当然你也可以通过一样的方式去约束其他的参数。通过httpMethod = new HttpMethodConstraint("GET","POST")可以约束该路由只能通过那种方式访问。
如果你的约束是上面无法做到的,那么下面的自定义约束一定会符合你的要求。新建一个自定义的约束只需要创建一个实现IRouteConstraint接口的类即可,比如我们限制只能是谷歌浏览器才能访问,新建一个Filters文件,并新建一个MyRouteConstraint类,写入如下的代码:
1 public class MyRouteConstraint : IRouteConstraint
2 {
3
4 public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
5 {
6 return httpContext.Request.UserAgent.Contains("Chrome");
7 }
8 }
接着我们换到不同的浏览器去测试,就会发现区别了(如果你通过浏览器的开发者工具或者其他工具修改UserAgent的话也可以越过这个约束,如Filddler2工具)
解决与物理路径的冲突
当发送一个请求至ASP.NET MVC时,其实会检查网站中存不存在这个请求的物理路径文件,如果存在的话,就会直接将这个物理文件返回。但是有时候我们需要它执行控制器的某个方法,而不是直接将这个物理文件返回。那么我们就需要这节知识。下面我们先在网站根目录中新建一个 Test.html ,在其中随便写上一些内容,然后访问。再在RouteConfig.cs中写入如下代码:
1 public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.RouteExistingFiles = true;
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }
这个时候我们再重新刷新浏览器,那么我们就可以看到控制器返回的结果了,这样我们就解决了物理路径和路由之间的冲突问题了。
8.绕过路由系统
如果我们有一些URL路径不希望通过路由系统,那么我们就可以利用这节知识。
下面是RouteConfig.cs的内容:
1 public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.IgnoreRoute("webResources.axd{*pathinfo}");
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }
9.自定义路由系统
如果上面的技术还无法解决你的问题,那么我们下面将会介绍如何自定义路由系统。自定义路由系统只需要继承RouteBase并实现两个方法,如下:
(1):GetRouteData
(2):GetVirtualPath
下面是我写的一个简单示例,用来判断访问者是否是移动设备,如果是移动设备则路由到前缀为M的控制器处理请求,否则返回NULL交由默认的路由
处理,下面为我的源码:
1 public class CustomRouteBase : RouteBase
2 {
3 private List<String> userAgent;
4
5 public CustomRouteBase(params String[] userAgents)
6 {
7 userAgent = userAgents.ToList();
8 }
9
10 public override RouteData GetRouteData(HttpContextBase httpContext)
11 {
12 RouteData rd = new RouteData(this, new MvcRouteHandler());
13 Regex r = new Regex(@"/(\w+)", RegexOptions.IgnoreCase);
14 MatchCollection mc = r.Matches(httpContext.Request.Path);
15 String agent = httpContext.Request.UserAgent.ToLower();
16 foreach (String item in userAgent)
17 {
18 if (agent.Contains(item))
19 {
20 if (mc.Count >= 2)
21 {
22 rd.Values.Add("controller", "M" + mc[0].Groups[1].Value.ToString());
23 rd.Values.Add("action", mc[1].Groups[1].Value.ToString());
24 }
25 else
26 {
27 rd.Values.Add("controller", "MHome");
28 rd.Values.Add("action", "Index");
29 }
30 return rd;
31 }
32 }
33 return null;
34 }
35
36 public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
37 {
38 return null;
39 }
40 }
最后我们将该自定义路由添加进来(RouteConfig.cs):
1 public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.Add(new CustomRouteBase("iphone", "ipad", "android"));
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }
现在你新建一个MHome的控制器,然后访问看看(建议使用Google浏览器,并通过开发者工具改变UserAgent即可快速看到效果)。
10.自定义路由处理程序
或许你会觉得ASP.NET MVC的控制器太麻烦,相比而言有些功能你更希望使用一般处理程序。但是访问的时候必须使用物理路径又发觉麻烦,那么通过学习这节,你将可以将一般处理程序也加入到路由中,并且可控性很强。
首先我们必须新建一个实现IRouteHandler接口的类:
1 public class DonwloadHandler : IRouteHandler
2 {
3
4 public IHttpHandler GetHttpHandler(RequestContext requestContext)
5 {
6 return new CustomHandler();
7 }
8 }
9
10 public class CustomHandler : IHttpHandler
11 {
12
13 public bool IsReusable
14 {
15 get { return false; }
16 }
17
18 public void ProcessRequest(HttpContext context)
19 {
20 context.Response.Write("download model");
21 }
22 }
你们可以看到上面的源码,我是直接在下面新建了一个实现IHttpHandler的类,并且在GetHttpHandler中将该类的实例返回,当然你还可以在这个方法中进行判断以便根据实际情况交由不同的一般处理程序去处理请求。
下面就是将这个路由处理程序添加到路由中,这里我们映射到MyTest这个路径:
1 public class RouteConfig
2 {
3 public static void RegisterRoutes(RouteCollection routes)
4 {
5 routes.Add(new Route("MyTest",new DonwloadHandler()));
6
7 routes.MapRoute(
8 name: "Default2",
9 url: "Test.html",
10 defaults: new { controller = "Home", action = "List" }
11 );
12 }
13 }
接着我们访问http://localhost:2392/MyTest就可以看到结果了。
装载:http://www.cnblogs.com/yaozhenfa/