URL Routing

URL Routing模型是用来将浏览器输入的请求(requests)映射为MVC controller actions。

1、使用默认的Route表

当你创建ASP.NET MVC应用程序时,就已经配置为使用URL Routing的应用程序。URL Routing创建于两个地方。

一、在Web.config启用URL Routing。在Web.config文件中存在4个和Routing关联的sections,system.web.httpModules 、system.web.httpHandlers 、system.webserver.modules、 和system.webserver.handlers。

二、Route表创建于Global.asax文件中

 public class MvcApplication : System.Web.HttpApplication
    {
        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);}
    }
对于这里参数如果不为空时,可以对应Action:Index(int id)和Index()。但是如果Action为:Index(int id)则传入的参数不能为空。
2、自定义URL Routing
创建一个匹配任何以/Archive/开头的Request的Route:
  public static void RegisterRoutes(RouteCollection routes)
  {
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
     routes.MapRoute(
          "blog",                       //自定义route必须出现在default之前,否则它不会被调用
          "Archive/{entryDate}",        //匹配任何以'/Archive/’开头的请求
          new { controller = "Archive", action = "Entry" });
     routes.MapRoute(
          "Default",                                              // Route name
          "{controller}/{action}/{id}",                           // URL with parameters
          new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
     );
  }
自定义route必须出现在默认Route之前。
3、MVC的URL Routing实现

ControllerBase类实现了IController接口,而该接口只提供一个方法void Execute(RequestContext)。RequestContext基的构造方法需要的参数类型HttpContextBase和HttpContext很相似。

 public class RequestContext
    {
        public RequestContext(HttpContextBase httpContext, RouteData routeData);
        public HttpContextBase HttpContext { get; }
        public RouteData RouteData { get; }
    }

从这可以看出MVC中URL Routing介入的起始点就在RequestContext类。

    public class RouteData
    {
        public RouteData();
        public RouteData(RouteBase route, IRouteHandler routeHandler);
        public RouteValueDictionary DataTokens { get; }
        public RouteBase Route { get; set; }
        public IRouteHandler RouteHandler { get; set; }
        public RouteValueDictionary Values { get; }
        public string GetRequiredString(string valueName);
    }

RouteBase 类:

    public abstract class RouteBase
    {
        protected RouteBase();
        public abstract RouteData GetRouteData(HttpContextBase httpContext);
        public abstract VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values);
    }

要研究透URL Routing,首先就必须清晰上面RouteData类中提到RouteValueDictionary、IRouteHandler。Route初始化时使用RouteValueDictionary来加入默认值及规则到Route中,而IRouteHandler的则提供了一个GetHttpHandler方法来获取用于处理URL的IHttpHandler。其接口定义如下:

  public interface IRouteHandler
    {
        IHttpHandler GetHttpHandler(RequestContext requestContext);
    }

GetHttpHandler输入参数是RequestContext ,而IHttpHandler 的ProcessRequest方法处理的参数则是HttpContext。这也就是URL Routing首次和HttpContext打交道的地方。如是实现这个转换呢?

//在构造方法中传入RequestContext 参数,用以设置页面RequestContext

public class MyPage:IHttpHandler 
{ 
    public RequestContext RequestContext { get; private set; } 
    public MyPage(RequestContext context) 
    { 
            this.RequestContext = context; 
    } 
    #region IHttpHandler  
    public virtual void ProcessRequest(HttpContext context)
	{ //将访问页面如a_b_c_index.aspx转换为a/b/c/index.aspx
		context.Server.Execute(RequestContext.RouteData.Values["page"].ToString().Replace("_","/")+".aspx"); 
	} 
    public bool IsReusable { get { return false; } } 
    #endregion 
}
//实现IRouteHandler 
public class MyRouteHandler : IRouteHandler 
{ 
    #region IRouteHandler  
    public IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
        return new MyPage(requestContext); 
    } 
    #endregion 
}
这样我们就可以在Golbal.asax的Application_Start事件中写如下代码
RouteTable.Routes.Add(new Route("{page}.aspx",new MyRouteHandler()));
posted @ 2009-03-15 09:19  俩醒叁醉  阅读(445)  评论(0编辑  收藏  举报