随着 ASP.NET MVC Beta 及 .net3.5 sp1 的发布,System.Web.Routing组件也正式和大家见面了。这里简单介绍一下如何使用Routing来进行URL路由(URL重写)。
假设我们要访问URL:http://localhost:4541/123456.aspx
但要求实际访问的URL:http://localhost:4541/Product.aspx?id=123456
这样我们就需要在请求URL的过程中对URL进行处理,如果使用System.Web.Routing?
1、安装.NET3.5 SP1补丁,当然你也可以直接拷贝这个组件。
2、在Web项目中引用System.Web.Routing这个组件。
3、实现IHttpHandler。我们创建一个ProductHttpHandler用以实现IHttpHandler接口,同时在实现中保存一个RequestContext对象。
public
class
ProductHttpHandler : IHttpHandler
{
public
RequestContext RequestContext {
get
;
private
set
; }
public
ProductHttpHandler(RequestContext context)
{
this
.RequestContext
=
context;
}
public
void
ProcessRequest(HttpContext context)
{
string
url
=
string
.Format(
"
Product.aspx?id={0}
"
, RequestContext.RouteData.Values[
"
id
"
]);
context.Server.Execute(url);
}
public
bool
IsReusable {
get
{
return
false
; } }
}
注意:
#、RequestContext对象是Routing组件中的类。
#、保存了一个只能通过构造函数初始化的RequestContext对象。
#、ProcessRequest方法中构造出真实访问的URL,然后交给Server.Execute方法执行
#、通过RouteData的字典中读取实际匹配的url参数。
#、为了进行测试,需要创建一下Product.aspx页面,然后返回id参数以便于测试:
protected
void
Page_Load(
object
sender, EventArgs e)
{
Response.Write(Request.QueryString[
"
id
"
]);
}
4、实现IRouteHandler。我们在为系统的RouteCollection集中中添加Route对象需要一个实现了IRouteHandler接口的对象,所以我们创建一个这样子的实现ProductRouteHandler。
public
class
ProductRouteHandler : IRouteHandler
{
public
IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return
new
ProductHttpHandler(requestContext);
}
}
实现上GetHttpHandler也没做什么事情,就是实例化一个我们刚才创建的IHttpHandler实现,实际上是要把控件权交给IHttpHandler处理。
5、在Global.asax.cs的Application_Start事件初始化路由表。
public
class
Global : System.Web.HttpApplication
{
public
static
void
RegisterRoutes(RouteCollection routes)
{
routes.Add(
new
Route(
"
{id}.aspx
"
,
new
ProductRouteHandler()));
}
protected
void
Application_Start(
object
sender, EventArgs e)
{
RegisterRoutes(RouteTable.Routes);
}
}
#、RouteTable.Routes是一个只读属性,它返回一个单件的RouteCollection集合
#、通过向RouteCollection集合中添加一系列的路由(Route)规则,来让系统自动为请求选择合适的URL指向。
6、最后,如果你创建的是一个普通的网站或者web application,这样可能没有对System.Web.Routing组行自动配置,你可以通地手动配置一下:
<
compilation
debug
="false"
>
<
assemblies
>
<
add
assembly
="System.Web.Routing, Version=3.5.0.0, Culture=neutral,
PublicKeyToken=31BF3856AD364E35"
/>
</
assemblies
>
</
compilation
>
<
pages
>
<
namespaces
>
<
add
namespace
="System.Web.Routing"
/>
</
namespaces
>
</
pages
>
<
system.web
>
<
httpModules
>
<
add
name
="UrlRoutingModule"
type
="System.Web.Routing.UrlRoutingModule,
System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
/>
</
httpModules
>
</
system.web
>
<
system.webServer
>
<
modules
runAllManagedModulesForAllRequests
="true"
>
<
remove
name
="UrlRoutingModule"
/>
<
add
name
="UrlRoutingModule"
type
="System.Web.Routing.UrlRoutingModule,
System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
/>
</
modules
>
</
system.webServer
>
注意:添加httpmodule需要在system.web和system.webServer节中都要进行配置。
好了,现在浏览页面http://localhost:4541/123456.aspx时就会显示出123456来了。
后续:
关于正则表达式
Route也可以使用正则表达式,只有符合指定的格式的URL才可以参与到本Route的路由,把访问权交给指定的页面。
RegisterRoutes
public static void RegisterRoutes(RouteCollection routes)
{
//正则表达式
routes.Add("r2", new Route("{id}.aspx",
new RouteValueDictionary(new { id = "1" }),
new RouteValueDictionary(new { id="[\\d]+" }),
new ProductRouteHandler()));
}
#第一个RouteValueDictionary用于设定Route的Url模板中的参数的默认值,这个字典也可以把一些需要配置的值利用这个通道传给IHttpHandler的实现进行处理。
#第二个RouteValueDictionary用于设定参数的格式,此处使用的是正则表达式,只有合符格式的url才会被本Route处理,否则就会下移到下一下Route
此时如果访问http://localhost:4541/abc.aspx就会报404错误,访问123.aspx才能正常访问。
关于路由表顺序
从刚才的述说中可以知道,url的处理是按由上到下的顺序进行匹配的,能匹配的url就被当前的Route处理,不能匹配的url就会下移到下一个Route匹配。
所以如果我们在刚才的注册方法之前添加了一个更容易匹配的格式 这样第二个Route就永远不会执行了。
RegisterRoutes
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add("r1", new Route("{id}.aspx", new ProductRouteHandler()));
//正则表达式
routes.Add("r2", new Route("{id}.aspx",
new RouteValueDictionary(new { id = "1" }),
new RouteValueDictionary(new { id="[\\d]+" }),
new ProductRouteHandler()));
}
未完成.....
#关于VirtualPath
我们如何通过程序来生成一个符合指定格式的URL,而不是通过手工构造?
#关于HttpMethodConstraint