System.Web.Routing入门及进阶 上篇

System.Web.Routing已经作为一个程序集包含在.net3.5sp1中发布了。虽然我们并没有在3.5sp1中发现Asp.net Mvc的踪迹,但是亦以感觉到它离我们不远了。

System.Web.Routing用于在Asp.netWeb应用程序中进行URLRouting

 

所谓UrlRouting就是将一个地址映射为另一个地址,比如我访问/chsword/2008/08/27.html其实是访问了/chsword/article.aspx?y=2008&m=08&d=27这个地址,URLRouting使我们的URL看起来非常漂亮。

 

本文将分2部分介绍UrlRouting的使用分别为入门篇与进阶篇。

文章的前提:

1.         安装Visual Studio 2008 sp1或其它IDE的等同版本。

2.         建立一个Asp.net Web ApplicationAsp.net Web应用程序)

3.         引用System.Web.Routing程序集。

UrlRouting的实现原理

如果你不是追求理论的人,仅仅是务实主义,可以直接从准备工作读起。

为了方便大家理解我绘制了一个UML图,其中通过RouteTableRoutes这个属性可以获取一个RouteCollectionSingleton模式,虽然在其中并没有判断值不存在时才初始化的Singleton的标志性行为,但是它是在Application_Start事件中进行初始化的,并且直到应用程序进程终结,所以是Singleton模式的。

 

而通过以下方式将Route添加到RouteTable.Routes

RouteTable.Routes.Add(new Route());

以上代码仅为表示其流程,这个代码是不能正确执行的,因为Route没有提供无参构造函数。

Route初始化时则是利用RouteValueDictionary来加入默认值及规则到Route

另外Route还有一个IRouteHandler的实现对象,IRouteHandler的实现对象提供了一个GetHttpHandler方法来获取用于处理URLIHttpHandler

 

这么说还是停留在抽象层次的,下面我们以一些简单例子来带你驭起UrlRouting

准备工作

由于须要一个处理UrlIHttpHandler所以我们先定义一个实现了IHttpHandler接口的类。

就叫它MyPage,由于我们要与IRouteHandler交互,所以除了实现IHttpHandler的方法之外还要声明一个RequestContext类型的属性

public class MyPage:IHttpHandler {
        
public RequestContext RequestContext { getprivate set; }
        
public MyPage(RequestContext context)
        {
            
this.RequestContext = context;
        }
        
#region IHttpHandler 成员
        
public virtual void ProcessRequest(HttpContext context){}
        
public bool IsReusable {
            
get { return false; }
        }
        
#endregion
    }

这样我们就拥有了一个自己的IHttpHandler

下面我们实现一个IRouteHandler

    public class MyRouteHandler : IRouteHandler {
        
#region IRouteHandler 成员
        
public IHttpHandler GetHttpHandler(RequestContext requestContext) {
            
return new MyPage(requestContext);
        }
        
#endregion
    }

这里实现了IRouteHandlerGetHttpHandler方法,使之返回刚才我们实现的MyPage

这样我们前期的2个工作就做完了,我们可以来实现UrlRouting了。

实现第一个UrlRouting

其实UrlRouting在定义完上两个规则后就很简单了。

Golbal.asax(没有可以新建一个)的Application_Start事件中写如下代码

 

protected void Application_Start(object sender, EventArgs e) {
            RegisterRoutes(RouteTable.Routes);
        }
        
public static void RegisterRoutes(RouteCollection routes) {
            routes.Add(
new Route("{page}.aspx",new MyRouteHandler()));
        }

这样我们就定义了第一个UrlRouting规则就是对xxxx.aspx这类的Url进行Routing

 

但是我们仅仅是定义了处理了什么样的Url,却没定义如何处理。

我们应该在刚刚定义的MyPageProcessRequest方法中定义如何处理。

我们将ProcessRequest方法实现如下:

 

public virtual void ProcessRequest(HttpContext context){
context.Server.Execute(        RequestContext.RouteData.Values[
"page"].ToString().Replace("_","/")+".aspx"
            );
}

很显然这里的RequestContext.RouteData.Values["page"]就是取到刚才的规则{page}.aspx中的page的值即,如果我访问index.aspxRequestContext.RouteData.Values["page"]就是index

我这里的定义是将”_”替换为”/”所以就是将list_index.aspx这样的URL转到list/index.aspx这样的网页上。

我们建立一些测试用的网页如下图所示:

 

 

在这些网页里随意写些可以分辨网页的文字。

则访问list_chsword.aspx时自动Routing到了list/chsword.aspx上了

总结一下UrlRouting与以下有关:

1.         Application_Start中定义的规则

2.         自己实现的IHttpHandler

 

这样您对于UrlRouting就算是入门了,下一篇我们将来讲一些进阶设置。

 

预计内容:

  • 规则的默认值
  • 正则规则设置
  • 使用技巧

 

 System.Web.Routing入门及进阶 下篇

 

 

posted @ 2008-08-27 11:47 重典 阅读(26520) 评论(29) 编辑 收藏

 回复 引用 查看   
#1楼2008-08-27 11:51 | Gray Zhang      
正好博问里有人问怎么用routing定位到web service,因为web service本身不是IHttpHandler,楼主有什么方法吗
 回复 引用 查看   
#2楼[楼主]2008-08-27 12:07 | 重典      
@Gray Zhang
我感觉并不在于IHttpHandler吧

可以将自己定义的IHttpHandler的ProcessRequest实现为
public virtual void ProcessRequest(HttpContext context)
{

WebService1 w=new WebService1();
context.Response.Write(w.HelloWorld());
context.Response.End();
}

类似这样

当然我这里简单写了,可以自己实现用Reflection来通过UrlRouting的不同调用不同的方法

当然可以序列化为SOAP或JSON输出。

 回复 引用 查看   
#3楼2008-08-27 12:25 | Gray Zhang      
主要是,web service可以选择性地序列化为xml或者json,而这里的w.HelloWorld()很可能返回的是一个对象,如何序列化对象的任务不应该交由自己实现的IHttpHandler嘛,不然不就是把web service的proxy重新做了一遍……
 回复 引用 查看   
#4楼[楼主]2008-08-27 12:30 | 重典      
@Gray Zhang
嗯,是的,我再试试其它方法

 回复 引用 查看   
#5楼2008-08-27 12:37 | 陛下      
了解,看上去比早前是有进步了。支持!
 回复 引用 查看   
#6楼[楼主]2008-08-27 12:42 | 重典      
@陛下
多谢^^

 回复 引用 查看   
#7楼2008-08-27 13:56 | 隐姓埋名      
藏之~
 回复 引用 查看   
#8楼[楼主]2008-08-27 14:06 | 重典      
@隐姓埋名
^^

 回复 引用 查看   
#9楼2008-08-27 16:27 | 巫云      
好多框架都用这样的URL重写了。
 回复 引用 查看   
#10楼[楼主]2008-08-27 16:29 | 重典      
@巫云
这个算是最官方的版本了

 回复 引用 查看   
#11楼2008-11-13 09:08 | 逸之羊      
学习了!
 回复 引用 查看   
#12楼2008-12-26 16:35 | 玉开      
ZHEYANG做UrlRewrite就方便了。
 回复 引用 查看   
#13楼2009-01-13 10:19 | 房子小轩      
学了半天,
web.config中没有注册这个,怎么也搞不定!
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

 回复 引用 查看   
#14楼[楼主]2009-01-13 10:56 | 重典      
@房子小轩
不好意思,因为前提于ASP.NET MVC的所以没有说明

 回复 引用 查看   
#15楼2009-01-13 14:18 | 房子小轩      
@重典
  我贴出来只是为了让其他跟我一样的菜鸟,注意一下~
  没有其他的意思~
  :)

 回复 引用 查看   
#16楼[楼主]2009-01-13 14:50 | 重典      
@房子小轩
呵呵,知道知道,我也仅是补充一下文中不足,呵呵
兄弟是刚刚来园子吗?

 回复 引用 查看   
#17楼2009-03-10 15:52 | stg609      
那Urlrewriter和asp.net routing有什么区别吗?听说routing的话只能访问到web控件,而urlrewriter则可以访问任何控件,比如HTML控件。是这样吗?
 回复 引用 查看   
#18楼[楼主]2009-03-10 18:42 | 重典      
@stg609
其实区别挺大的,
首先就是实现原理不一样,一个于IHttpHandler一个早于它
使用URLWrite时URL只能硬编码
比如首页index.html,你都要写死了

但UrlRouting却可能动态生成,更改规则时自动也生成相应的连接

 回复 引用 查看   
#19楼2009-04-10 15:48 | Dreaming      
重典同志,首先非常感谢你给我们提供的视频~致敬~~
另外有个问题请教一下,正式版的MVC像以下定义router不行吗?
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
routes.MapRoute(
"Member",
"Member/{action}.htm",
new { controller = "Member", action = "Login" }
);
这是我在老赵的视频上看到的,他这样写看上去很方便,不用写IRouteHandler了,但我这像他这样写去匹配不到,反正只匹配第一条规则。请问用这样的写法吗??疑惑ing

 回复 引用 查看   
#20楼[楼主]2009-04-10 16:38 | 重典      
@Dreaming
MapRoute是可以用的,而且一直可以,但它是ASP.NET MVC中写的对Route的一个扩展方法,本身不属于Routing

而我写这篇 文章是针对Routing的 和ASP.NET MVC也基本没什么关系,为做到通用性,所以没有在文中使用任何依赖于其它框架的方法

 回复 引用   
#21楼2009-06-15 16:16 | 疑问[未注册用户]
RequestContext 这个类是在哪个命名空间下,一直没有找着
 回复 引用 查看   
#22楼[楼主]2009-06-15 16:18 | 重典      
@疑问
是属性,不是类

 回复 引用 查看   
#23楼2010-01-27 15:20 | 梅桦      
请问这个是在传统的webform上利用System.Web.Routing实现还是在mvc项目里实现的?

谢谢!

 回复 引用 查看   
#24楼[楼主]2010-01-27 16:01 | 重典      
@梅桦
是WebForm的

 回复 引用 查看   
#25楼[楼主]2010-01-27 16:01 | 重典      
@梅桦
MVC中使用时默认工程就有示例

 回复 引用 查看   
#26楼2010-02-01 15:06 | Harold Shen      
LZ
我按照你的步骤写了代码,我也下载了你的代码运行,可是好像有点问题,为什么当我直接运行的时候并不会调用进入 MyRouteHandler.GetHttpHandler,只有当我在地址栏输入错误的URL时,这个事件才会被触发。

这种情况发生同样发生在你的sample上。

 回复 引用 查看   
#27楼2010-02-01 15:09 | Harold Shen      
我发现原因了,是因为匹配的物理文件被发现了就不去routing 了,于是我设置routes.RouteExistingFiles = true; 楼主因该加入这句代码。
 回复 引用 查看   
#28楼2011-01-10 14:24 | nyth      
public virtual void ProcessRequest(HttpContext context){
......
}
你好,这个方法我开来看去,不知道是谁调用了,然后执行了它!还是它自动之行的。


 回复 引用 查看   
#29楼2011-11-02 14:43 | Locer John      
楼主啊,我照着你这个做了,怎么没效果啊。
Web/Default.aspx也没变成Web_Default.aspx
况且本来就是Web/Default.aspx斜杠的形式。
[img]C:\Documents and Settings\admin\桌面\1.jpg[/img]