恳求如何进入ASP.NET MVC框架_.docx

上传人:PIYPING 文档编号:11653254 上传时间:2021-08-28 格式:DOCX 页数:16 大小:16.72KB
返回 下载 相关 举报
恳求如何进入ASP.NET MVC框架_.docx_第1页
第1页 / 共16页
恳求如何进入ASP.NET MVC框架_.docx_第2页
第2页 / 共16页
恳求如何进入ASP.NET MVC框架_.docx_第3页
第3页 / 共16页
恳求如何进入ASP.NET MVC框架_.docx_第4页
第4页 / 共16页
恳求如何进入ASP.NET MVC框架_.docx_第5页
第5页 / 共16页
亲,该文档总共16页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《恳求如何进入ASP.NET MVC框架_.docx》由会员分享,可在线阅读,更多相关《恳求如何进入ASP.NET MVC框架_.docx(16页珍藏版)》请在三一文库上搜索。

1、恳求如何进入ASP.NET MVC框架_ 这篇文章主要介绍了恳求如何进入ASP.NET MVC框架的实现过程,感爱好的小伙伴们可以参考一下 一、前言 对于WebForm开发,恳求通常是一个以.aspx结尾的url,对应一个物理文件,从代码的角度来说它其实是一个控件(Page)。而在MVC中,一个恳求对应的是一个Controller里的Action。熟识的伴侣都知道,恳求实际都是交给HttpHandler处理(实现了IHttpHandler的类型)。无论是.aspx,.ashx,.asmx 还是MVC里的Action,恳求都会交给HttpHandler。具体是在管道大事中,会依据恳求创建一个Ht

2、tpHandler,并执行它的PR方法。对于aspx和ashx都很好理解,由于它们本身就实现了IHttpHandler接口,而MVC的Controller和Action都和HttpHandler没有关系,它是如何实现的呢?接下来我们就看一个恳求是如何进入mvc框架内部的。 二、例子 WebForm和MVC都是建立在平台上的,Webform消失得比较早,那么MVC是如何做到在不影响底层框架,实现扩展的呢?这主要得益于的路由机制。路由机制并不属于MVC,WebForm也可以用法它。它的目的是让一个恳求与物理文件分别,原理是通过映射关系,将恳求映射到指定的HttpHandler。例如我们也可以将一个

3、/Admin/User.aspx?name=张三 的恳求映射成可读性更好的/Admin/张三。下面是两种url的注册方式: public static void RegisterRoutes(RouteCollection routes) /MVC routes.MapRoute( name: Default, url: controller/action/id, defaults: new controller = Home, action = Index, id = UrlParameter.Optional ); /WebForm routes.MapPageRoute( routeNa

4、me: WebForm, routeUrl: Admin/user, physicalFile: /Admin/User.aspx ); RouteCollection是一个Route集合,Route封装了名称、url模式、约束条件、默认值等路由相关信息。其中,MapPageRoute是RouteCollection定义的方法,而MapRoute是MVC扩展出来的(扩展方法的好处就是可以在不修改原有代码的状况下添加所需的功能)。它们的目的都是一样的,创建一个Route对象,添加到集合当中;我们也可以new 一个Route对象,然后调用RouteCollection.Add,效果是一样的。下面我

5、们主要关注MVC的实现过程,WebForm其实也是类似的。 三、分析源码 接下来我们看MVC是如何利用路由机制实现扩展的。路由机制是通过一个UrlRoutingModule完成的,它是一个实现了IHttpModule的类,路由模块已经默认帮我们注册好了。HttpModule通过注册HttpApplication大事参加到管道处理恳求中,具体是订阅HttpApplication某个阶段的大事。路由机制就是利用这个原理,UrlRoutingModule订阅了PostResolveRequestCache 大事,实现url的映射。为什么是该大事呢?由于该大事的下一步就要完成恳求和物理文件的映射,所以

6、必需要此之前进行拦截。核心代码如下: public class UrlRoutingModule : IHttpModule public RouteCollection RouteCollection get if (_routeCollection = null) /全局的RouteCollection集合 _routeCollection = RouteTable.Routes; return _routeCollection; set _routeCollection = value; protected virtual void Init(HttpApplication applic

7、ation) /注册PostResolveRequestCache大事 application.PostResolveRequestCache += OnApplicationPostResolveRequestCache; private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) /创建上下文 HttpApplication app = (HttpApplication)sender; HttpContextBase context = new HttpContextWrapper(app.Co

8、ntext); PostResolveRequestCache(context); public virtual void PostResolveRequestCache(HttpContextBase context) /1.猎取RouteData RouteData routeData = RouteCollection.GetRouteData(context); if (routeData = null) return; /2.猎取IRouteHandler IRouteHandler routeHandler = routeData.RouteHandler; if (routeHa

9、ndler = null) /RequestContext保证了HttpContext和RouteData,在后续用法 RequestContext requestContext = new RequestContext(context, routeData); context.Request.RequestContext = requestContext; /3.猎取IHttpHandler IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); /重新映射处处理程序 context.RemapHandl

10、er(httpHandler); 我们关注主要方法PostResolveRequestCache,这里有三个关键步骤。 步骤一. 猎取RouteData RouteData是对Route的包装,在后续的处理中用法。它的猎取是通过RouteCollection获得的,这个和上面注册用到的RouteTable.Routes是同一个集合对象。调用RouteCollection的GetRouteData会遍历它的每一个项,也就是Route对象,然后调用Route对象的GetRouteData方法(MVC内部许多集合都用到了这种设计)。如下代码: public RouteData GetRouteDat

11、a(HttpContextBase httpContext) using (GetReadLock() foreach (RouteBase route in this) RouteData routeData = route.GetRouteData(httpContext); if (routeData != null) return routeData; return null; Route对象的GetRouteData方法如下: public override RouteData GetRouteData(HttpContextBase httpContext) string requ

12、estPath = httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2) + httpContext.Request.PathInfo; /结合默认值,匹配url RouteValueDictionary values = _parsedRoute.Match(requestPath, Defaults); if (values = null) return null; /包装成RouteData,这里为什么不放在if后面呢? RouteData routeData = new RouteData(this,

13、RouteHandler); /匹配约束 if (!ProcessConstraints(httpContext, values, RouteDirection.IncomingRequest) return null; /RouteData的Values和DataTokens都来自于Route foreach (var value in values) routeData.Values.Add(value.Key, value.Value); if (DataTokens != null) foreach (var prop in DataTokens) routeData.DataToke

14、nsprop.Key = prop.Value; return routeData; 可以看到,Route对象的GetRouteData方法会匹配url模式,和检查约束条件,如何不符合会返回null。假如匹配,则new一个RouteData。 步骤二、猎取IRouteHandler接口对象 上面创建RouteData,参数分别是当前Route对象和它的RouteHandler属性。RouteHandler是一个IRouteHandler,这是一个重要接口,它的定义如下: public interface IRouteHandler IHttpHandler GetHttpHandler(Req

15、uestContext requestContext); 很明显,它是用于猎取IHttpHandler的。那么Route对象的RouteHandler属性又是在哪里初始化的呢?我们回到开头的注册方法,routes.MapRoute,这个方法依据传递的参数创建一个Route对象,该方法的实现如下: public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string namespaces) /创建一个Route对象

16、,它的IRouteHandler为MvcRouteHandler Route route = new Route(url, new MvcRouteHandler() Defaults = CreateRouteValueDictionary(defaults), Constraints = CreateRouteValueDictionary(constraints), DataTokens = new RouteValueDictionary() ; if (namespaces != null) (namespaces.Length 0) route.DataTokensNamespac

17、es = namespaces; /将Route注册到RouteCollection中 routes.Add(name, route); return route; 在创建Route时,除了传递url模式外,还默认帮我们传递了一个MvcRouteHandler,它实现了IRouteHandler接口。 步骤三、猎取IHttpHandler接口对象 有了MvcRouteHandler,就可以调用它的GetHttpHandler方法猎取IHttpHandler了,该方法实现如下: protected virtual IHttpHandler GetHttpHandler(RequestContex

18、t requestContext) /设置session状态 requestContext.HttpContext.SetSessionStateBehavior(GetSessionStateBehavior(requestContext); /返回一个实现了IHttpHandler的MvcHandler return new MvcHandler(requestContext); 可以看到,它返回了一个MvcHandler,MvcHandler就实现了IHttpHandler接口。所以开头说的,恳求本质都是交给HttpHandler的,其实MVC也是这样的,恳求交给了MvcHandler处

19、理。我们可以看MvcHandler定义和主要方法: public class MvcHandler : IHttpAsyncHandler, IHttpHandler, IRequiresSessionState protected internal virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, object state) IController controller; IControllerFactory factory; /这个方法里会激活Contr

20、oller对象 ProcessRequestInit(httpContext, out controller, out factory); IAsyncController asyncController = controller as IAsyncController; if (asyncController != null) / asynchronous controller BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) try /调用Controll

21、er的BeginExecute方法 return asyncController.BeginExecute(RequestContext, asyncCallback, asyncState); catch factory.ReleaseController(asyncController); throw; ; EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult) try asyncController.EndExecute(asyncResult); finally factory.ReleaseControll

22、er(asyncController); ; SynchronizationContext syncContext = SynchronizationContextUtil.GetSynchronizationContext(); AsyncCallback newCallback = AsyncUtil.WrapCallbackForSynchronizedExecution(callback, syncContext); return AsyncResultWrapper.Begin(newCallback, state, beginDelegate, endDelegate, _proc

23、essRequestTag); else / synchronous controller Action action = delegate try controller.Execute(RequestContext); finally factory.ReleaseController(controller); ; return AsyncResultWrapper.BeginSynchronous(callback, state, action, _processRequestTag); 可以看到,MvcHandler的任务就是激活Controller,并执行它的Execute方法。这个过

24、程和Webform里的页面处理是很相像的,.aspx恳求到来,会依据虚拟路径找到实现IHttpHandler的Page(类似于路由机制依据url模式找到MvcHandler),然后进入Page的页面周期(类似于Mvc的激活Controller,然后执行Action过程)。 四、总结 接下来,简洁总结一下恳求进入到MVC框架的过程: 1.添加路由对象Route到全局的RouteCollection,Route的IRouteHandler初始化为MvcRouteHandler。 2. UrlRoutingModule注册 HttpApplication PostResolveRequestCache大事,实现恳求拦截。 3. 恳求到来, 在处理大事中遍历RouteCollection,调用每一个Route对象的GetRouteData猎取RouteData包装对象。 4. 调用MvcRouteHandler的GetHttpHandler猎取MvcHandler。 5. 调用HttpContext的RemapHandler将恳求映射到MvcHandler处理程序。 6. 执行MvcHandler的PR方法,激活Controller,执行Action。 以上就是本文的全部内容,盼望对大家的学习有所关心。 .

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 科普知识


经营许可证编号:宁ICP备18001539号-1