您的位置:首页 > 编程语言 > ASP

ASP.NET 路由系统

2013-01-25 11:48 429 查看
asp.net 的url路由系统,最初是为了实现Url与物理文件路径的分离而建立的,后来的asp.net mvc也是对asp.net路由系统的扩展,将url与物理文件映射转为url与目标controller/action的映射。

1.请求的URL与物理文件的分离

简单通过一个Demo来演示:
场景:一个页面展示员工列表,点击员工姓名显示员工详细信息
RouteCollection

public class RouteCollection : Collection<RouteBase>
{
//其他成员
//返回有关集合中与指定值匹配的路由的信息
public RouteData GetRouteData(HttpContextBase httpContext);
//如果具有指定的上下文和参数值,则返回与路由关联的 URL 路径的相关信息
public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
//如果具有指定的上下文、路由名称和参数值,则返回与命名路由关联的 URL 路径的相关信息
public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values);
//定义不需检查是否匹配路由的 URL 模式
public void Ignore(string url);

/***eg:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default",                                              // Route name
"{controller}/{action}/{id}",                           // URL with parameters
new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
);
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
}
*/
//定义一个 URL 模式,此模式在请求 URL 满足指定约束的情况下不需要检查 URL 是否与路由匹配
public void Ignore(string url,Object constraints);
//eg:routes.Ignore("{*allaspx}", new {allaspx=@".*\.aspx(/.*)?"});
//提供用于定义 Web 窗体应用程序的路由的方法
public Route MapPageRoute(
string routeName,
string routeUrl,
string physicalFile,
bool checkPhysicalUrlAccess,
RouteValueDictionary defaults,
RouteValueDictionary constraints,
RouteValueDictionary dataTokens
);
/*
* routes.MapPageRoute("ExpenseDetailRoute",
"ExpenseReportDetail/{locale}/{year}/{*queryvalues}", "~/expenses.aspx",
false,
new RouteValueDictionary
{ { "locale", "US" }, { "year", DateTime.Now.Year.ToString() } },
new RouteValueDictionary
{ { "locale", "[a-z]{2}" }, { "year", @"\d{4}" } },
new RouteValueDictionary
{ { "account", "1234" }, { "subaccount", "5678" } });

*/
}


对现有文件路由

注册路由:

protected void Application_Start(object sender, EventArgs e)
{
var defaults = new RouteValueDictionary { { "areacode", "010" }, { "days", 2 }};
var dataTokens = new RouteValueDictionary { { "defaultCity", "BeiJing" }, { "defaultDays", 2 } };
RouteTable.Routes.MapPageRoute("default", "{areacode}/{days}","~/weather.aspx", false, defaults, null, dataTokens);
}


weather页面用来展示当前RouteData的各项属性,当直接请求http://.../weather.aspx时,页面的RouteData各项属性都为空,所以ASP.NET没有对请求地址实施路由
解决方案:在注册路有前加上一句:RouteTable.Routes.RouteExistingFiles=true;这句话是说需要对存在的物理文件实施路由,也就是说如果请求的URL与某个物理文件的路径地址一致的情况下是否还需要对其实施路由,该属性默认值为false,

注册路由忽略地址

但问题出现了,我们在页面weather.aspx引用了样式Style.css,采用RouteExistingFiles=true,意味着Style.css访问也会被路由,然后导向weather.aspx这个页面,这样一来无法正常在页面引用js和css文件了。
解决方案:
在注册路由之前加上一句:RouteTable.Routes.Ignore("{filename}.css/{*pathInfo}");,但是这句话必须在路由注册之前执行。

直接添加路由对象

我们调用RouteCollection对象的MapPageRoute方法进行路由注册的本质是在路由字典中添加Route,所以我们可以自己手工Add一个Route对象,

//路由注册方式1
routes.MapPageRoute("ExpenseDetailRoute",
"ExpenseReportDetail/{locale}/{year}/{*queryvalues}", "~/expenses.aspx",
false,
new RouteValueDictionary
{ { "locale", "US" }, { "year", DateTime.Now.Year.ToString() } },
new RouteValueDictionary
{ { "locale", "[a-z]{2}" }, { "year", @"\d{4}" } },
new RouteValueDictionary
{ { "account", "1234" }, { "subaccount", "5678" } });

//路由注册方式2
Route route=new Route("ExpenseReportDetail/{locale}/{year}/{*queryvalues}",
new RouteValueDictionary
{ { "locale", "US" }, { "year", DateTime.Now.Year.ToString() } },
new RouteValueDictionary
{ { "locale", "[a-z]{2}" }, { "year", @"\d{4}" } },
new RouteValueDictionary
{ { "account", "1234" }, { "subaccount", "5678" } },
new PageRouteHandler("~/expenses.aspx",false));
RouteTable.Routes.Add("default",route);


2.根据路由规则生成URL

ASP.NET的路由系统主要有两个方面的应用

通过注册URL模版与物理文件的匹配实现请求地址和物理地址的分离

通过注册的路由规则生成一个响应的URL,通过RouteCollection的GetVirtualPath方法来实现

public class RouteCollection : Collection<RouteBase>
{
//其他成员..

//如果具有指定的上下文和参数值,则返回与路由关联的 URL 路径的相关信息
public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
//如果具有指定的上下文、路由名称和参数值,则返回与命名路由关联的 URL 路径的相关信息
public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values);
}


GetVirtualPath方法
如果requestContext参数为null,这种情况会基于当前HTTP上下文(对应HttpContext的静态属性Current)创建一个RequestContext对象作为GetVirtualPath的参数。如果RouteData为空,则抛出异常
路由对象针对GetVirtualPath方法而进行的路由匹配只要求URL模版中定义的变量的值都能被提供,这些变量值具有3个来源:

路由对象定义的默认变量值

指定RequestContext的RouteData提供的变量值(Values属性)

手工提供的变量值(通过values参数指定的RouteValueDictionary对象)

public class RouteCollection : Collection<RouteBase>
{
//其他成员..

//如果具有指定的上下文和参数值,则返回与路由关联的 URL 路径的相关信息
public VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
//如果具有指定的上下文、路由名称和参数值,则返回与命名路由关联的 URL 路径的相关信息
public VirtualPathData GetVirtualPath(RequestContext requestContext, string name, RouteValueDictionary values);
}


protected void Page_Load(object sender,EventArgs e)
{
//1.指定RequestContext的RouteData提供的Values属性
RouteData routeData =new RouteData();
routeData.Values.Add("areaCode","010");
routeData.Values.Add("days","2");
//封装到RequestContext中
RequestContext requestContext=new RequestContext();
//包装当前HttpContext
requestContext.HttpContext =new HttpContextWrapper(HttpContext.Current);
requestContext.RouteData=routeData;

//2.手工指定参数values
RouteValueDictionary values=new RouteValueDictionary();
values.Add("areaCode","028");
values.Add("days","3");

Reponse.Write(RouteTable.Routes.GetVirtualPath(null,null).VirtualPath);//输出注册路有时指定的默认路由值

Reponse.Write(RouteTable.Routes.GetVirtualPath(requestContext,null).VirtualPath);//输出:/010/2

Reponse.Write(RouteTable.Routes.GetVirtualPath(requestContext,values).VirtualPath);//输出:/028/3
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: