ASP.NET路由模型解析
作者:网络转载 发布时间:[ 2016/3/8 11:31:47 ] 推荐标签:测试开发技术 .NET
如我们所料UrlRoutingModule实现了IHttpModule接口,我们看看它的Init方法干了些什么?
protected virtual void Init(HttpApplication application)
{
if (application.Context.Items[_contextKey] == null)
{
application.Context.Items[_contextKey] = _contextKey;
application.PostResolveRequestCache += new EventHandler(this.OnApplicationPostResolveRequestCache);
}
}
对第7个事件PostResolveRequestCache注册方法OnApplicationPostResolveRequestCache,那么这个方法又是干啥的呢?
public virtual void PostResolveRequestCache(HttpContextBase context)
{
RouteData routeData = this.RouteCollection.GetRouteData(context);
//匹配路由,得到匹配结果RouteData。
if (routeData != null)
{
IRouteHandler routeHandler = routeData.RouteHandler;
if (routeHandler == null)
{
throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, SR.GetString("UrlRoutingModule_NoRouteHandler"), new object[0]));
}
if (!(routeHandler is StopRoutingHandler))
{
RequestContext requestContext = new RequestContext(context, routeData);
context.Request.RequestContext = requestContext;
IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
//获取处理当前请求的IHttpHandler对象。
if (httpHandler == null)
{
object[] args = new object[] { routeHandler.GetType() };
throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.GetString("UrlRoutingModule_NoHttpHandler"), args));
}
if (httpHandler is UrlAuthFailureHandler)
{
if (!FormsAuthenticationModule.FormsAuthRequired)
{
throw new HttpException(0x191, SR.GetString("Assess_Denied_Description3"));
}
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current, this);
}
else
{
context.RemapHandler(httpHandler);
//映射:用当前IHttpHandler对象处理请求。
}
}
}
}
代码已经加了注释,3步走:匹配路由→获取处理当前请求的IHttpHandler对象→映射:用当前IHttpHandler对象处理请求。之后会在第11、12个事件之间调用IHttpHandler对象的PR方法处理当前请求。
我们再整理下思路:ASP.NET先注册了UrlRoutingModule模块,他是一个实现了IHttpModule接口的类,其Init方法是在第7个事件上注册一个方法,该方法先匹配路由,如果匹配成功了,则用匹配结果RouteData中的IHttpHandler对象映射到当前上下文中,这样在之后第11、12个事件之间会调用这个IHttpHandler对象处理请求。
那么问题来了,Route对象是什么时候注入进去的,IHttpHandler对象又是谁?
还记得路由规则是怎么添加的吗?如下面代码所示:
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
var defaults = new RouteValueDictionary();
defaults.Add("name", "*");
//方式一:
//通过RouteTable的静态对象Routes新增一个Route类型的对象。
RouteTable.Routes.Add("app", new Route("app/{name}", defaults, new MyRouteHandler()));
//方式二:
//通过RouteTable的静态对象Routes的扩展方法新增一个路由规则。
RouteTable.Routes.MapPageRoute("default", "app/{name}", "~/WebForm1.aspx", false, defaults);
}
}
这是我们经常用的两种方式添加路由规则,方式一中有我们自己编写的MyRouteHandler类型的实例作为参数,其实是通过IRouteHandler接口返回一个IHttpHandler对象。
/// <summary>
/// 实现了IRouteHandler接口的类型
/// </summary>
internal class MyRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
//返回一个Page对象,用于处理请求。
return new WebForm1();
}
}
其实这两种方式没有本质上的区别,因为方式二中路由规则参数都会实例化一个Route对象的。
我们分析方式二的源代码:
public Route MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints, RouteValueDictionary dataTokens)
{
if (routeUrl == null)
{
throw new ArgumentNullException("routeUrl");
}
Route item = new Route(routeUrl, defaults, constraints, dataTokens, new PageRouteHandler(physicalFile, checkPhysicalUrlAccess));
this.Add(routeName, item);
return item;
}
发现所有的路由规则参数都用来实例化一个Route对象了,其中参数physicalFile和checkPhysicalUrlAccess用来实例化PageRouteHandler对象了,其源码如下:
public class PageRouteHandler : IRouteHandler
{
}
这是一个实现了IRouteHandler接口的类型,而这个接口只有一个作用是返回IHttpHandler对象,源码如下:
[TypeForwardedFrom("System.Web.Routing, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
public interface IRouteHandler
{
// Methods
IHttpHandler GetHttpHandler(RequestContext requestContext);
}
到这里我们的疑问解开了,原来我们注册的路由规则都实例化成了Route对象,Route的GetRouteData方法用来匹配路由(参考博客园大神Artech的书籍),路由规则中的physicalFile和checkPhysicalUrlAccess用来实例化一个IHttpHandler实例,用来处理请求。
总结:ASP.NET的路由模型如下图所示
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Asp.net MVC如何对所有用户输入的字符串字段做Trim处理Asp.Net WebForm生命周期的详解asp.net 六大内置对象Linux使用Jexus托管Asp.Net Core应用程序asp.net登录验证码实现方法ASP.NET自带对象JSON字符串与实体类的转换ASP.NET MVC必须知道的那些事!Asp.net Core MVC中使用SessionASP.NET Core的配置(7):多样性的配置来源[下篇]ASP.NET Core的配置(6):多样性的配置来源[中篇]ASP.NET Core的配置(5):多样性的配置来源ASP.NET实现License Key输入功能ASP.NET Core 1.0中的管道-中间件模式ASP.NET Core的配置(3): 将配置绑定为对象[上篇]ASP.NET Core的配置(2):配置模型详解ASP.NET中的随机密码生成
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11热门文章
常见的移动App Bug??崩溃的测试用例设计如何用Jmeter做压力测试QC使用说明APP压力测试入门教程移动app测试中的主要问题jenkins+testng+ant+webdriver持续集成测试使用JMeter进行HTTP负载测试Selenium 2.0 WebDriver 使用指南