约束路由
1、用正则表达式约束路由
有工程11-3URLTestDemo,如在Global.asax中有如下路由定义:
public static void RegisterRoutes(RouteCollection routes) { routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { Controller = "Home", Action = "Index", id = UrlParameter.Optional }, new { Controller="^H.*"}, new[] { "_11_3URLTestDemo.Controllers" }); }
这里的new[] { "_11_3URLTestDemo.Controllers" }表示优先匹配_11_3URLTestDemo.Controllers命名空间中的控制器,这是为了避免在不同的命名空间中有同名的控制器时出现命名冲突,通过此种方式可以指定匹配的优先顺序。
这里我们关注的是正则表达式来约束路由。约束被表示成一个匿名类型,该类型的属性对应到想要进行约束的片段变量名,例如这里就是Controller,表明后面的正则表达式"^H.*"是用来约束url中对应controller变量的值的。Controller="^H.*"表示只匹配Controller变量的值以"H"打头的url,url本身不区分大小写,这里的H也不区分大小写。
假设有两个控制器,一个是HomeController,另一个是AccountController,两个控制器里都定义有Index方法。那么对于上面的约束,如有url:
~/home 可以匹配
对于url:
~/Account 则不匹配。
=====
需要注意,这里Controller变量的默认值问题。默认值是在约束检查之前运用的。因此,如果请求的url是根目录"~/",Controller的默认值"Home"会被运用,然后才检查约束。但需要注意的是,这并不意味着不再做约束检查,事实上,检查仍然要做,如果通不过检查,url也不会匹配。
例如,将路由定义作如下修改,把Controller的默认值改为了Account:
public static void RegisterRoutes(RouteCollection routes) { routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { Controller = "Account", Action = "Index", id = UrlParameter.Optional }, new { Controller="^H.*"}, new[] { "_11_3URLTestDemo.Controllers" }); }
这个时候如果请求的url是根目录"~/",就无法匹配。因为默认值Account不能通过约束检查——第一个字母必须是H(不分大小写)。
2、约束到指定值
例如:
public static void RegisterRoutes(RouteCollection routes) { routes.MapRoute("MyRoute", "{controller}/{action}/{id}/{*catchall}", new { Controller = "Home", Action = "Index", id = UrlParameter.Optional }, new { Controller="^H.*", Action="^Index$|^About$"}, new[] { "_11_3URLTestDemo.Controllers" }); }
这里定义的路由匹配的url被约束为:Controller变量的值要以H(不分大小写)字母开头,而且Action变量必须是Index或About。
"~/Home/Index"
"~/Home/About"
这两个url可以匹配。
用这种方式可以限制到比较精确的url。
3、约束使用HTTP方法的路由
例如:
public static void RegisterRoutes(RouteCollection routes) { 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" }); }
这里定义的路由就限定了只能匹配使用GET方法进行请求的url。
注意这里的名字httpMethod是自己指定的,只要给它赋值为一个HttpMethodConstraint类的实例就可以了。
上面的例子限定了只能使用GET方法,也可以很容易的添加另外的方法:
httpMethod = new HttpMethodConstraint("GET", "POST")
4、单元测试:路由约束
测试路由约束时,最好对所要匹配的url和试图排除的url都进行测试。
例如:
[TestMethod] public void TestIncomingRoutes() { TestRouteMatch("~/", "Home", "Index"); TestRouteMatch("~/Home", "Home", "Index"); TestRouteMatch("~/Home/Index", "Home", "Index"); TestRouteMatch("~/Home/About", "Home", "About"); TestRouteMatch("~/Home/About/MyId", "Home", "About", new { id="MyId"}); TestRouteMatch("~/Home/About/MyId/More/Segments", "Home", "About", new { id = "MyId", catchall="More/Segments" }); TestRouteFail("~/Home/OtherAction"); TestRouteFail("~/Account/Index"); TestRouteFail("~/Account/About"); }
也可以测试HTTP方法。
重载TestRouteFail,增添一个参数httpMehod
private void TestRouteFail(string url, string httpMethod) { //布置 RouteCollection routes = new RouteCollection(); MvcApplication.RegisterRoutes(routes); //动作 RouteData result = routes.GetRouteData(CreateHttpContext(url, httpMethod)); //断言 Assert.IsTrue(result == null || result.Route == null); }
下面就可以测试对HTTP方法的约束:
[TestMethod] public void RegisterRoutesTest() { TestRouteMatch("~/", "Home", "Index", null, "get"); TestRouteFail("~/", "POST"); }
-lyj