完整的生命周期比较复杂,对细节感兴趣的同学可购买老A的图书学习:传送门

本文只简单讲述路由注册、controller创建、action选择的3个主逻辑线,其他的内容大家可自己阅读相应的代码

先上二者单独的生命周期介绍文档:  mvc生命周期  ,   web api生命周期

以下内容以vs创建的默认mvc 、webapi 项目为准分析,不足之处,敬请体谅

Mvc

 Web Api(web host)

1、路由注册、处理、解析对应handler

UrlRoutingModule通过重载IHttpModule来接管mvc和webapi的处理

以下为简要逻辑代码(删减了部分)

 protected virtual void Init(HttpApplication application) {
application.PostResolveRequestCache += OnApplicationPostResolveRequestCache;
} private void OnApplicationPostResolveRequestCache(object sender, EventArgs e) {
HttpApplication app = (HttpApplication)sender;
HttpContextBase context = new HttpContextWrapper(app.Context);
PostResolveRequestCache(context);
} public virtual void PostResolveRequestCache(HttpContextBase context) {
// Match the incoming URL against the route table
RouteData routeData = RouteCollection.GetRouteData(context); // If a route was found, get an IHttpHandler from the route's RouteHandler
IRouteHandler routeHandler = routeData.RouteHandler; RequestContext requestContext = new RequestContext(context, routeData); IHttpHandler httpHandler = routeHandler.GetHttpHandler(requestContext);
if (httpHandler == null) {
throw new InvalidOperationException(
String.Format(
CultureInfo.CurrentUICulture,
SR.GetString(SR.UrlRoutingModule_NoHttpHandler),
routeHandler.GetType()));
} // Remap IIS7 to our handler
context.RemapHandler(httpHandler);
}

逻辑为:从注册的RouteData中解析RouteHandler,然后再调用GetHttpHandler获取相应的IHttpHandler

mvc中的HttpHandler是MvcHandler

webapi中的是               HttpControllerHandler

所以路由注册的目标是:注册+指定handler

下面看下二者的不同

//WebApiApplication.cs
RouteConfig.RegisterRoutes(RouteTable.Routes);

//RouteConfig.cs
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

RouteTable.Routes 作为注册入口,

在MapRoute中指定RouteHandler为MvcRouteHandler的处理器

然后再获取IHttpHandler

//MvcRouteHandler.cs
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
requestContext.HttpContext.SetSessionStateBehavior(this.GetSessionStateBehavior(requestContext));
return (IHttpHandler) new MvcHandler(requestContext);
}
//WebApiApplication.cs
GlobalConfiguration.Configure(WebApiConfig.Register);
//WebApiConfig.cs
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);

GlobalConfiguration.HttpConfiguration 作为注册入口,

并在HostedHttpRoute中指定RouteHandler为HttpControllerRouteHandler

然后再获取IHttpHandler

//HttpControllerRouteHandler.cs
protected virtual IHttpHandler GetHttpHandler(RequestContext requestContext)
{
return (IHttpHandler) new HttpControllerHandler(requestContext.RouteData);
}

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));
}
internal async Task ProcessRequestAsyncCore(HttpContextBase contextBase)
{
HttpRequestMessage request = contextBase.GetHttpRequestMessage() ?? HttpControllerHandler.ConvertRequest(contextBase);
request.SetRouteData(this._routeData);
CancellationToken cancellationToken = contextBase.Response.GetClientDisconnectedTokenWhenFixed();
HttpResponseMessage response = (HttpResponseMessage) null;
try
{
     //创建HttpMessageHandler管道,只有最后一个为 HttpMessageHandler衍生类,其余皆为子类DelegatingHandler的衍生类
response = await this._server.SendAsync(request, cancellationToken);
await HttpControllerHandler.CopyResponseAsync(contextBase, request, response, HttpControllerHandler._exceptionLogger.Value, HttpControllerHandler._exceptionHandler.Value, cancellationToken);
}
catch (OperationCanceledException ex)
{
...
}
  ...
}

通过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);

   //5种过滤器
FilterInfo filters = this.GetFilters(controllerContext, action);
try
{
     //身份过滤器
  AuthenticationContext authenticationContext = this.InvokeAuthenticationFilters(controllerContext, filters.AuthenticationFilters, action);
  if (authenticationContext.Result != null)
  {
  AuthenticationChallengeContext challengeContext = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, action, authenticationContext.Result);
  this.InvokeActionResult(controllerContext, challengeContext.Result ?? authenticationContext.Result);
  }
  else
  {
       //权限过滤器
  AuthorizationContext authorizationContext = this.InvokeAuthorizationFilters(controllerContext, filters.AuthorizationFilters, action);
  if (authorizationContext.Result != null)
  {
    AuthenticationChallengeContext challengeContext = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, action, authorizationContext.Result);
    this.InvokeActionResult(controllerContext, challengeContext.Result ?? authorizationContext.Result);
  }
  else
  {
         //action 过滤器
    if (controllerContext.Controller.ValidateRequest)
    ControllerActionInvoker.ValidateRequest(controllerContext);
    IDictionary<string, object> parameterValues = this.GetParameterValues(controllerContext, action);
    ActionExecutedContext actionExecutedContext = this.InvokeActionMethodWithFilters(controllerContext, filters.ActionFilters, action, parameterValues);
    AuthenticationChallengeContext challengeContext = this.InvokeAuthenticationFiltersChallenge(controllerContext, filters.AuthenticationFilters, action, actionExecutedContext.Result);
    this.InvokeActionResultWithFilters(controllerContext, filters.ResultFilters, challengeContext.Result ?? actionExecutedContext.Result);
  }
  }
}
catch (Exception ex)
{
     //异常过滤器
ExceptionContext exceptionContext = this.InvokeExceptionFilters(controllerContext, filters.ExceptionFilters, ex);
if (!exceptionContext.ExceptionHandled)
throw;
else
this.InvokeActionResult(controllerContext, exceptionContext.Result);
}
return true;
}

//ApiController.cs
public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
this.Initialize(controllerContext); ServicesContainer services = controllerContext.ControllerDescriptor.Configuration.Services;
HttpActionDescriptor actionDescriptor = services.GetActionSelector().SelectAction(controllerContext);
this.ActionContext.ActionDescriptor = actionDescriptor;
  
//4种过滤器
FilterGrouping filterGrouping = actionDescriptor.GetFilterGrouping();
IActionFilter[] actionFilters = filterGrouping.ActionFilters;
IAuthenticationFilter[] authenticationFilters = filterGrouping.AuthenticationFilters;
IAuthorizationFilter[] authorizationFilters = filterGrouping.AuthorizationFilters;
IExceptionFilter[] exceptionFilters = filterGrouping.ExceptionFilters;
IHttpActionResult innerResult = (IHttpActionResult) new ActionFilterResult(actionDescriptor.ActionBinding, this.ActionContext, services, actionFilters);
if (authorizationFilters.Length > )
innerResult = (IHttpActionResult) new AuthorizationFilterResult(this.ActionContext, authorizationFilters, innerResult);
if (authenticationFilters.Length > )
innerResult = (IHttpActionResult) new AuthenticationFilterResult(this.ActionContext, this, authenticationFilters, innerResult);
if (exceptionFilters.Length > )
{
IExceptionLogger logger = ExceptionServices.GetLogger(services);
IExceptionHandler handler = ExceptionServices.GetHandler(services);
innerResult = (IHttpActionResult) new ExceptionFilterResult(this.ActionContext, exceptionFilters, logger, handler, innerResult);
}
return innerResult.ExecuteAsync(cancellationToken);
}
   
   

Asp.net Mvc 与 Web Api生命周期对比的更多相关文章

  1. asp.net MVC 应用程序的生命周期

    下面这篇文章总结了 asp.net MVC 框架程序的生命周期.觉得写得不错,故转载一下. 转载自:http://www.cnblogs.com/yplong/p/5582576.html       ...

  2. vs 2013下自定义ASP.net MVC 5/Web API 2 模板(T4 视图模板/控制器模板)

    vs 2013下自定义ASP.net MVC 5/Web API 2  模板(T4 视图模板/控制器模板): Customizing ASP.NET MVC 5/Web API 2 Scaffoldi ...

  3. ASP.NET MVC+Knockout+Web API+SignalR

    架构设计(ASP.NET MVC+Knockout+Web API+SignalR) 架构设计(ASP.NET MVC+Knockout+Web API+SignalR) 2014-01-16 18: ...

  4. Visual Studio 2013 Preview - ASP.NET, MVC 5, Web API 2新功能搶先看

    Visual Studio 2013 Preview - ASP.NET, MVC 5, Web API 2新功能搶先看 來自TechEd North America 2013的第一手消息 以下資訊均 ...

  5. ABP示例程序-使用AngularJs,ASP.NET MVC,Web API和EntityFramework创建N层的单页面Web应用

    本片文章翻译自ABP在CodeProject上的一个简单示例程序,网站上的程序是用ABP之前的版本创建的,模板创建界面及工程文档有所改变,本文基于最新的模板创建.通过这个简单的示例可以对ABP有个更深 ...

  6. ASP.NET MVC和Web API中的Angular2 - 第2部分

    下载源码 内容 第1部分:Visual Studio 2017中的Angular2设置,基本CRUD应用程序,第三方模态弹出控件 第2部分:使用Angular2管道进行过滤/搜索,全局错误处理,调试客 ...

  7. [Asp.Net] MVC 和Web API Action 获取参数的区别

    Asp.net MVC 和web api 的action 在获取从前台传入的数据是有很大不同 前台使用ajax的方式向后台发起post的请求 Content-Type:application/json ...

  8. asp.net MVC 应用程序的生命周期(上)

    首先我们知道http是一种无状态的请求,他的生命周期就是从客户端浏览器发出请求开始,到得到响应结束.那么MVC应用程序从发出请求到获得响应,都做了些什么呢? 本文我们会详细讨论MVC应用程序一个请求的 ...

  9. Asp.Net MVC及Web API框架配置会碰到的几个问题及解决方案(转)

      前言 刚开始创建MVC与Web API的混合项目时,碰到好多问题,今天拿出来跟大家一起分享下.有朋友私信我问项目的分层及文件夹结构在我的第一篇博客中没说清楚,那么接下来我就准备从这些文件怎么分文件 ...

随机推荐

  1. 智能合约语言 Solidity 教程系列5 - 数组介绍

    写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果你还不了解,建议你先看以太坊是什么 本文前半部分是参考Solidity官方文档(当前最新版本: ...

  2. CET-4- translation1

    questions 2017/10/17 多年来,家长和老手都曾得到过这样一种信息(message):尽量利用任何机会表扬孩子,对他们所干的任何事情都要说好.据说这样做有助于提高孩子的自尊.但是近来许 ...

  3. bzoj 3531: [Sdoi2014]旅行

    Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. ...

  4. mybatis源码分析(一)

    mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...

  5. Nginx (二) Nginx的反向代理负载均衡以及日志切割

    Nginx是一个高并发,高性能的服务器,可以进行反向代理以及网站的负载均衡.这些功能的运用都在配置文件中,也就是Nginx安装目录下的conf/nginx.conf. nginx.conf 1. 先来 ...

  6. python 爬去拉钩测试招聘信息

    代码如下: #coding:utf-8 import time import urllib.request from bs4 import BeautifulSoup file=open(r'meit ...

  7. [数据清洗]- Pandas 清洗“脏”数据(三)

    预览数据 这次我们使用 Artworks.csv ,我们选取 100 行数据来完成本次内容.具体步骤: 导入 Pandas 读取 csv 数据到 DataFrame(要确保数据已经下载到指定路径) D ...

  8. 微信小程序之页面路由

    路由方式 简介 对于路由的触发方式以及页面生命周期函数如下: 路由方式 触发时机 路由前页面 路由后页面 初始化 小程序打开的第一个页面   onLoad, onSHow 打开新页面 调用 API w ...

  9. 记一次Hbase查询速度优化经历

    项目背景: 在这次影像系统中,我们利用大数据平台做的是文件(图片.视频等)批次的增删改查,每个批次都包含多个文件,上传完成以后要添加文件索引(文件信息及批次信息),由于在Hbase存储的过程中,每个文 ...

  10. 【Python3之模块及包的导入】

    一.模块导入 1.定义 Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句. 模块让你能够有逻辑地组织你的 Python ...