ASP.NET MVC 3—一切的开始MvcHandler、MvcHttpHandler
2011-05-25 22:42
435 查看
在ASP.NETMVC3里面,一次用户请求是如何开始的呢?
如果下载了MVC的源代码进行调试,一般来说会发现开始于MvcHandler,简单看下MvcHandler的代码,主要就是通过控制器的工厂接受控制器的实例,并使用控制器进行进一步处理,那么MvcHandler是如果被创建,如何被调用执行的?
首先看看MvcHandler的构造函数,是没有无参的构造函数,显然看来MvcHandler单干是有点难度了。直接查找MvcHandler的所有引用,很容易在MvcRouteHandler中可以找到:
[code]requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
而且使用MvcHandler构造函数的地方有且仅有这么一个,明显我们找到我们想要的东西了。
接下来就需要弄清楚MvcRouteHandler的GetHttpHandler什么时候执行的,看源代码的时候,“查找所有引用”是很好用的功能,在RouteCollectionExtensions里面可以看到:
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这个就比较好理解了,MvcRouteHandler实现了IRouteHandler接口,因此可以与路由模块进行集成,当我们在Global.asax文件中使用MapRoute方法时,会向路由模块注册MvcRouteHandler实例,当MvcRouteHandler被调用的时候,会创建RequestContext实例产生MvcHandler的实例,并使用MvcHandler实例进一步进行处理。查看在UrlRoutingModule的代码可以看到:
[code]{
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
到此为止MvcHandler的整个创建过程就差不都已经弄清楚,那么接下来继续介绍MvcHttpHandler,也许有人会问既然已经有MvcHandler了为什么还需要MvcHttpHandler呢?
其实前面也提到过了,MvcHandler没有无参的构造函数,因此即使MvcHandler实现了IHttpHandler接口,在IIS中也不能将其映射为某类文件扩展名的处理程序,需要结合路由模块使用。那么MvcHttpHandler就提供了不通过路由模块的情况下直接处理映射的处理程序。
至于如何将某类文件扩展名映射到一个MVC处理程序,在此就不多做介绍,但MvcHttpHandler带无参的构造函数,而且继承UrlRoutingHandler类实现了IHttpHandler接口,因此可以在ASP.NET程序中灵活的使用用来解决一些问题。
例如创建一个普通的MVC3项目,但在项目中添加一个WebForm页面TestPage.aspx,在页面的后台文件TestPage.aspx.cs文件中添加如下代码:
[code]{
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
然后直接访问/TestPage.aspx页面,会发现实际访问返回了/Home/About页面。
调试查看访问/TestPage.aspx执行的过程,还会发现最终还是使用到MvcHandler,至于为什么会这样子?有兴趣的话可以看下UrlRoutingHandler的ProcessRequest的逻辑就能够理解了。
如果下载了MVC的源代码进行调试,一般来说会发现开始于MvcHandler,简单看下MvcHandler的代码,主要就是通过控制器的工厂接受控制器的实例,并使用控制器进行进一步处理,那么MvcHandler是如果被创建,如何被调用执行的?
首先看看MvcHandler的构造函数,是没有无参的构造函数,显然看来MvcHandler单干是有点难度了。直接查找MvcHandler的所有引用,很容易在MvcRouteHandler中可以找到:
protectedvirtualIHttpHandlerGetHttpHandler(RequestContextrequestContext){
[code]requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext));
returnnewMvcHandler(requestContext);
}
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
而且使用MvcHandler构造函数的地方有且仅有这么一个,明显我们找到我们想要的东西了。
接下来就需要弄清楚MvcRouteHandler的GetHttpHandler什么时候执行的,看源代码的时候,“查找所有引用”是很好用的功能,在RouteCollectionExtensions里面可以看到:
publicstaticRouteMapRoute(thisRouteCollectionroutes,stringname,stringurl,objectdefaults,[code] objectconstraints,string[]namespaces){
if(routes==null){
thrownewArgumentNullException("routes");
}
if(url==null){
thrownewArgumentNullException("url");
}
Routeroute=newRoute(url,newMvcRouteHandler()){
Defaults=newRouteValueDictionary(defaults),
Constraints=newRouteValueDictionary(constraints),
DataTokens=newRouteValueDictionary()
};
if((namespaces!=null)&&(namespaces.Length>0)){
route.DataTokens["Namespaces"]=namespaces;
}
routes.Add(name,route);
returnroute;
}
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
这个就比较好理解了,MvcRouteHandler实现了IRouteHandler接口,因此可以与路由模块进行集成,当我们在Global.asax文件中使用MapRoute方法时,会向路由模块注册MvcRouteHandler实例,当MvcRouteHandler被调用的时候,会创建RequestContext实例产生MvcHandler的实例,并使用MvcHandler实例进一步进行处理。查看在UrlRoutingModule的代码可以看到:
publicvirtualvoidPostResolveRequestCache(HttpContextBasecontext)
[code]{
RouteDatarouteData=this.RouteCollection.GetRouteData(context);
if(routeData!=null)
{
IRouteHandlerrouteHandler=routeData.RouteHandler;
if(routeHandler==null)
{
thrownewInvalidOperationException(string.Format(CultureInfo.CurrentUICulture,
SR.GetString("UrlRoutingModule_NoRouteHandler"),newobject[0]));
}
if(!(routeHandlerisStopRoutingHandler))
{
RequestContextrequestContext=newRequestContext(context,routeData);
context.Request.RequestContext=requestContext;
IHttpHandlerhttpHandler=routeHandler.GetHttpHandler(requestContext);
if(httpHandler==null)
{
thrownewInvalidOperationException(string.Format(CultureInfo.CurrentUICulture,
SR.GetString("UrlRoutingModule_NoHttpHandler"),newobject[]{routeHandler.GetType()}));
}
if(httpHandlerisUrlAuthFailureHandler)
{
if(!FormsAuthenticationModule.FormsAuthRequired)
{
thrownewHttpException(0x191,SR.GetString("Assess_Denied_Description3"));
}
UrlAuthorizationModule.ReportUrlAuthorizationFailure(HttpContext.Current,this);
}
else
{
context.RemapHandler(httpHandler);
}
}
}
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
到此为止MvcHandler的整个创建过程就差不都已经弄清楚,那么接下来继续介绍MvcHttpHandler,也许有人会问既然已经有MvcHandler了为什么还需要MvcHttpHandler呢?
其实前面也提到过了,MvcHandler没有无参的构造函数,因此即使MvcHandler实现了IHttpHandler接口,在IIS中也不能将其映射为某类文件扩展名的处理程序,需要结合路由模块使用。那么MvcHttpHandler就提供了不通过路由模块的情况下直接处理映射的处理程序。
至于如何将某类文件扩展名映射到一个MVC处理程序,在此就不多做介绍,但MvcHttpHandler带无参的构造函数,而且继承UrlRoutingHandler类实现了IHttpHandler接口,因此可以在ASP.NET程序中灵活的使用用来解决一些问题。
例如创建一个普通的MVC3项目,但在项目中添加一个WebForm页面TestPage.aspx,在页面的后台文件TestPage.aspx.cs文件中添加如下代码:
protectedvoidPage_Load(objectsender,EventArgse)
[code]{
HttpContext.Current.RewritePath("/Home/About");
IHttpHandlerhttpHandler=newMvcHttpHandler();
httpHandler.ProcessRequest(HttpContext.Current);
}
[/code]
.csharpcode,.csharpcodepre
{
font-size:small;
color:black;
font-family:consolas,"CourierNew",courier,monospace;
background-color:#ffffff;
/*white-space:pre;*/
}
.csharpcodepre{margin:0em;}
.csharpcode.rem{color:#008000;}
.csharpcode.kwrd{color:#0000ff;}
.csharpcode.str{color:#006080;}
.csharpcode.op{color:#0000c0;}
.csharpcode.preproc{color:#cc6633;}
.csharpcode.asp{background-color:#ffff00;}
.csharpcode.html{color:#800000;}
.csharpcode.attr{color:#ff0000;}
.csharpcode.alt
{
background-color:#f4f4f4;
width:100%;
margin:0em;
}
.csharpcode.lnum{color:#606060;}
然后直接访问/TestPage.aspx页面,会发现实际访问返回了/Home/About页面。
调试查看访问/TestPage.aspx执行的过程,还会发现最终还是使用到MvcHandler,至于为什么会这样子?有兴趣的话可以看下UrlRoutingHandler的ProcessRequest的逻辑就能够理解了。
相关文章推荐
- ASP.NET MVC 3—MvcHandler、MvcHttpHandler
- ASP.NET MVC 5-开始MVC5之旅
- ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇
- ASP.NET MVC Framework体验(1):从一个简单实例开始
- 深入分析ASP.NET Mvc 1.0 – 1. 深入MvcHandler
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目 (11)文件管理
- ASP.NET MVC 5-开始MVC5之旅
- ASP.NET MVC使用Bootstrap系列(1)——开始使用Bootstrap
- ASP.NET MVC使用Bootstrap系列(1)——开始使用Bootstrap
- ASP.NET MVC使用Bootstrap系列(1)——开始使用Bootstrap
- asp.net mvc 初次任务-从路由开始认识MVC
- ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇
- ASP.NET MVC Framework体验(1):从一个简单实例开始(转)
- ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.1) 登录功能的实现,开始接触Spring IOC、DI
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(5.5) 登录功能的实现,完善登录功能
- ASP.NET MVC 5-开始MVC5之旅
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目(7.2) 模块管理,模块的添加、修改、删除
- 【无私分享:从入门到精通ASP.NET MVC】从0开始,一起搭框架、做项目 登录界面前端样式和特效
- ASP.NET MVC Framework体验(1):从一个简单实例开始