Asp.net Mvc 与 Web Api生命周期对比
完整的生命周期比较复杂,对细节感兴趣的同学可购买老A的图书学习:传送门
本文只简单讲述路由注册、controller创建、action选择的3个主逻辑线,其他的内容大家可自己阅读相应的代码
先上二者单独的生命周期介绍文档: mvc生命周期 , web api生命周期
以下内容以vs创建的默认mvc 、webapi 项目为准分析,不足之处,敬请体谅
Mvc
|
Web Api(web host) |
1、路由注册、处理、解析对应handler
UrlRoutingModule通过重载IHttpModule来接管mvc和webapi的处理 以下为简要逻辑代码(删减了部分) ![]() 1 protected virtual void Init(HttpApplication application) { 2 application.PostResolveRequestCache += OnApplicationPostResolveRequestCache; 3 } 4 5 private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) { 6 HttpApplication app = (HttpApplication)sender; 7 HttpContextBase context = new HttpContextWrapper(app.Context); 8 PostResolveRequestCache(context); 9 } 10 11 public virtual void PostResolveRequestCache(HttpContextBase context) { 12 // Match the incoming URL against the route table 13 RouteData routeData = RouteCollection.GetRouteData(context); 14 15 // If a route was found, get an IHttpHandler from the route's RouteHandler 16 IRouteHandler routeHandler = routeData.RouteHandler; 17 18 RequestContext requestContext = new RequestContext(context, routeData); 19 20 IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext); 21 if (httpHandler == null) { 22 throw new InvalidOperationException( 23 String.Format( 24 CultureInfo.CurrentUICulture, 25 SR.GetString(SR.UrlRoutingModule_NoHttpHandler), 26 routeHandler.GetType())); 27 } 28 29 // Remap IIS7 to our handler 30 context.RemapHandler(httpHandler); 31 }
逻辑为:从注册的RouteData中解析RouteHandler,然后再调用GetHttpHandler获取相应的IHttpHandler mvc中的HttpHandler是MvcHandler webapi中的是 HttpControllerHandler 所以路由注册的目标是:注册+指定handler
下面看下二者的不同 |
|
//WebApiApplication.cs RouteTable.Routes 作为注册入口, 在MapRoute中指定RouteHandler为MvcRouteHandler的处理器 然后再获取IHttpHandler //MvcRouteHandler.cs
|
//WebApiApplication.cs //WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
GlobalConfiguration.HttpConfiguration 作为注册入口, 并在HostedHttpRoute中指定RouteHandler为HttpControllerRouteHandler 然后再获取IHttpHandler //HttpControllerRouteHandler.cs
|
2、创建Controller
|
|
为了方便理解逻辑,使用同步版本来描述,实际使用中,继承controller的都是使用一步版本 在上一步已经获取到 MvcHandler,接着显式调用 IHttpHandler.ProcessRequest 方法
void IHttpHandler.ProcessRequest(HttpContext httpContext) { this.ProcessRequest(httpContext); } protected virtual void ProcessRequest(HttpContext httpContext) { this.ProcessRequest((HttpContextBase) new HttpContextWrapper(httpContext)); } protected internal virtual void ProcessRequest(HttpContextBase httpContext) { IController controller; IControllerFactory factory; this.ProcessRequestInit(httpContext, out controller, out factory); try { controller.Execute(this.RequestContext); } finally { factory.ReleaseController(controller); } } private void ProcessRequestInit(HttpContextBase httpContext, out IController controller, out IControllerFactory factory) { string requiredString = this.RequestContext.RouteData.GetRequiredString(nameof (controller)); factory = this.ControllerBuilder.GetControllerFactory(); controller = factory.CreateController(this.RequestContext, requiredString); }
上述ProcessRequestInit方法内部,只展示了基本逻辑, 通过ControllerFactory创建 Contrller, 之后调用 Controller.Execute 执行Controller创建Action的逻辑 |
同样,找到 HttpControllerHandler开始处理, web api在创建controller之前可对请求流做管道式处理, 可在请求消息到达路由选择前提前加入处理逻辑
//HttpTaskAsyncHandler.cs public abstract Task ProcessRequestAsync(HttpContext context); IAsyncResult IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { return TaskAsyncHelper.BeginTask(() => ProcessRequestAsync(context), cb, extraData); } void IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) { TaskAsyncHelper.EndTask(result); }
public override Task ProcessRequestAsync(HttpContext context) { return this.ProcessRequestAsyncCore((HttpContextBase) new HttpContextWrapper(context)); }
通过GlobalConfiguration.HttpConfiguration入口可配置自定义的HttpMessageHandler委托链,
其中HttpServer是第一个被执行的HttpMessageHandler, HttpRoutingDispatcher是最后一个,具体封装实现是在HttpServer.Initialize()中,如下:
protected virtual void Initialize() { this._configuration.EnsureInitialized(); this.InnerHandler = HttpClientFactory.CreatePipeline(this._dispatcher, (IEnumerable<DelegatingHandler>) this._configuration.MessageHandlers); }
作为最后一个handler的HttpRoutingDispatcher在构造函数中默认指定HttpControllerDispatcher为处理handler HttpControllerDispatcher才是真正的controller创建入口
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { ... try { HttpControllerDescriptor controllerDescriptor = this.ControllerSelector.SelectController(request); IHttpController controller = controllerDescriptor.CreateController(request); controllerContext = HttpControllerDispatcher.CreateControllerContext(request, controllerDescriptor, controller); return await controller.ExecuteAsync(controllerContext, cancellationToken); } catch (OperationCanceledException ex) { ... } HttpResponseMessage response = await this.ExceptionHandler.HandleAsync(exceptionContext, cancellationToken); return response; }
|
3、创建action
|
|
//ControllerBase类中方法 void IController.Execute(RequestContext requestContext) { this.Execute(requestContext); } protected virtual void Execute(RequestContext requestContext) { ... this.ExecuteCore(); } //Controller类中方法 protected override void ExecuteCore() { this.PossiblyLoadTempData(); try { string actionName = Controller.GetActionName(this.RouteData); if (this.ActionInvoker.InvokeAction(this.ControllerContext, actionName)) return; this.HandleUnknownAction(actionName); } finally { this.PossiblySaveTempData(); } } 对应的同步版本ControllerActionInvoker逻辑为: public virtual bool InvokeAction(ControllerContext controllerContext, string actionName) { ControllerDescriptor controllerDescriptor = this.GetControllerDescriptor(controllerContext); ActionDescriptor action = this.FindAction(controllerContext, controllerDescriptor, actionName);
|
//ApiController.cs
|