Routing with WebForms

http://haacked.com/archive/2008/03/11/using-routing-with-webforms.aspx
http://haacked.com/archive/2008/05/19/updated-routing-with-webforms.aspx

ASP.NET MVC 框架中包含了 Routing 的功能,由 System.Web.Routing 提供。但这个功能并不局限于 MVC,而且已经从中分离出来成为了一个独立的组件。

Phil Haack 的 blog 中提出一种办法可以配合 WebForm 使用 Routing 功能。这里有几个关键点。

首先,需要实现一个 IRouteHandler,它是一个 IHttpHandler 的提供者。

namespace System.Web.Routing
{
    
public interface IRouteHandler
    {
        IHttpHandler GetHttpHandler(RequestContext requestContext);
    }
}

这里 Phil 创建实现了一个 WebFormRouteHandler.  其关键代码如下:

namespace WebFormRouting
{
    
public class WebFormRouteHandler : IRouteHandler
    {
        
// 

        
public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            
// 根据 RouteData 得到被替换后的虚拟路径
            string virtualPath = GetSubstitutedVirtualPath(requestContext);

            
// 对 URL 进行身份验证(如果需要)
            if (this.CheckPhysicalUrlAccess && !UrlAuthorizationModule.CheckUrlAccessForPrincipal(virtualPath, requestContext.HttpContext.User, requestContext.HttpContext.Request.HttpMethod))
                
throw new SecurityException();

            
// 根据虚拟路径创建 Page 对象
            var page = BuildManager.CreateInstanceFromVirtualPath(virtualPath, typeof(Page)) as IHttpHandler;
            
if (page != null)
            {
                
//Pages that don't implement IRoutablePage won't have the RequestContext
                
//available to them. Can't generate outgoing routing URLs without that context.

                
// 查看页面是否实现了 IRoutablePage (包含 RequestContext 属性,可产生出去的 routing URLs)
                
// 设置其 RequestContext
                var routablePage = page as IRoutablePage;
                
if (routablePage != null)
                    routablePage.RequestContext 
= requestContext;
            }
            
return page;
        }
    }
}

在通过路由信息找到相关的 Page 后,能够通过 System.Web.Compilation.BuildManager 的 CreateInstanceFromVirtualPath 方法,接受一个虚拟路径和所需创建的 Page 类型,即可创建出相应的 Page 对象来处理请求。

我看了目前 ASP.NET MVC 框架的实现,其中默认的视图引擎 WebFormViewEngine 也是通过了这个方法来创建相关的 Page 对象。

需要注意的是,Routing 和 URL Rewrite 是有区别的,我的理解是 Routing 比 URL Rewrite 发生的更早,并不会在内部发起一个新的 Request.
因此 Phil 提到需要注意的一个安全问题,就是结合窗体身份验证时,如果不注意,Routing 会跳过身份验证这个环节的监测。因此,上面代码中的 UrlAuthorizationModule.CheckUrlAccessForPrincipal 方法调用就是对这个问题的补救。

同样基于这个区别的原因,Routing 的目标地址不可以带 QueryString 参数,变通的办法是可以通过 RouteData 传递参数。

posted on 2008-05-21 12:59  NeilChen  阅读(869)  评论(2编辑  收藏  举报

导航