1.变量默认值
由于我们为定义在URL模板中表示区号和天数的变量定义了默认值(areacode:010;days:2)如果希望返回返回北京未来两天的天气,可以直接访问应用根地址,也可以只指定具体区号,或者同时指定区号和天数。
默认情况下RouteData的Route属性返回的正是一个Route类型的对象,RouteHandler属性返回的则是一个PageRouteHandler的对象。针对请求URL实施路由解析得到的路由变量被保存在生成RouteData对象的Values属性中,而在路由注册过程为Route对象的DataTokens属性指定的路由变量被转移到了RouteData的同名变量中。
2.约束
我们以电话区号代表对应的城市,为了确保用户在请求地址中提供有效的区号,我们通过正则表达式(0\d{2,3})对其进行约束。除此之外,假设只能提供未来3天以内的天气情况,我们同样可以通过正则表达式([1-3])对请求地址中表示天数的变量进行约束。如果请求地址中的内容不符合相关变量段的约束条件,则意味着对应的路由对象与之不匹配。
对于约束,除了可以通过字符串的形式为某个变量定义相应的正则表达式之外,还可以指定一个RouteConstaint对象。所有的RouteConstraint类型均实现了IRouteConstraint接口,如下面的代码片段所示,该接口具有唯一的方法Math用于执行针对约束的检验。该方法有5个参数分别代表当前HTTP上下文、当前Route对象、路由变量的名称(存储约束对象在RouteValueDictionary中对应的key)、用于替换定义在路由模板中占位符的变量集合及路由方向。
public interface IRouteConstraint { bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) } public enum RouteDirection { IncomingRequest//正在处理客户端的URL UrlGeneration//正在根据路由定义创建 URL。 }
所谓“路由方向”表明路由检验是针对请求匹配(入栈)还是针对URL的生成(出栈),分别通过如上所示的枚举类型RouteDirection的两个枚举值表示。RouteBase类型的两个核心方法GetRouteData和GetVirtualPathData分别采用IncomingRequest和UrlGeneration作为路由方向。
ASP.NET路由系统的应用编程接口定义了如下一个实现了IRouteConstraint接口的HttpMethodConstraint类型。顾名思义,HttpMethodConstraint提供针对HTTP方法(GET、POST、PUT、DELETE等)的约束。如果我们通过HttpMethodConstraint为Route对象设置一个允许的HTTP方法列表,那么被路由的请求采用的HTTP方法必须在此列表中。这个被允许路由的HTTP方法列表对应着HttpMethodConstraint的只读属性AllowedMethods,该属性在构造函数中初始化。
public class HttpMethodConstraint { public HttpMethodConstraint(params string[] allowedMethods); protected virtual bool Match(HttpContextBase httpContext,Route route, string parameterName,RouteValueDictionary values,RouteDirection routeDirection); public ICollection<string> AllowedMethods { get; } }
同样是针对前面演示的例子,我们这次在进行路由注册的时候按照如下的方式将一个HttpMethodConstraint对象作为约束应用到被注册的Route对象上。此HttpMethodConstraint对象允许的HTTP方法列表只具有POST这个唯一的HTTP方法,意味着被注册的Route对象仅限于路由POST请求。
public class Global : System.Web.HttpApplication { protected void Application_Start(object sender, EventArgs e) { var defaults = new RouteValueDictionary { { "areacode", "010" }, { "days", 2 } }; var constaints = new RouteValueDictionary { { "areacode", @"0\d{2,3}" }, { "days", @"[1-3]{1}" }, { "httpMethod", new HttpMethodConstraint("POST") } }; var dataTokens = new RouteValueDictionary { { "defaultCity", "BeiJing" }, { "defaultDays", 2 } }; RouteTable.Routes.MapPageRoute("default", "{areacode}/{days}","~/weather.aspx", false, defaults, constaints, dataTokens); } }
现在我们采用与注册的模板相匹配的地址(/010/2)来访问页面,就会是404错误了。