现在我们从代码角度来看下,从消息处理管道末尾是怎么创建出Controller实例的。消息处理管道末端是一个叫HttpRoutingDispatcher的处理器,其内部完成路由后 ,会把消息派送给其内部的一个消息处理器HttpControllerDispatcher来完成Controller实例创建。

一、流程示意图

二、代码说明

我们先看下HttpControllerDispatcher代码,主要看下SendAsync方法:

public class HttpControllerDispatcher : HttpMessageHandler
{
private readonly HttpConfiguration _configuration; private IExceptionLogger _exceptionLogger;
private IExceptionHandler _exceptionHandler;
private IHttpControllerSelector _controllerSelector; /// <summary>
/// Initializes a new instance of the <see cref="HttpControllerDispatcher"/> class.
/// </summary>
public HttpControllerDispatcher(HttpConfiguration configuration)
{
if (configuration == null)
{
throw Error.ArgumentNull("configuration");
} _configuration = configuration;
} /// <summary>
/// Gets the <see cref="HttpConfiguration"/>.
/// </summary>
public HttpConfiguration Configuration
{
get { return _configuration; }
} /// <remarks>This property is internal and settable only for unit testing purposes.</remarks>
internal IExceptionLogger ExceptionLogger
{
get
{
if (_exceptionLogger == null)
{
_exceptionLogger = ExceptionServices.GetLogger(_configuration);
} return _exceptionLogger;
}
set
{
_exceptionLogger = value;
}
} /// <remarks>This property is internal and settable only for unit testing purposes.</remarks>
internal IExceptionHandler ExceptionHandler
{
get
{
if (_exceptionHandler == null)
{
_exceptionHandler = ExceptionServices.GetHandler(_configuration);
} return _exceptionHandler;
}
set
{
_exceptionHandler = value;
}
} //从服务容器里直接获取默认的HttpControllerSelector
private IHttpControllerSelector ControllerSelector
{
get
{
if (_controllerSelector == null)
{
_controllerSelector = _configuration.Services.GetHttpControllerSelector();
} return _controllerSelector;
}
} protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw Error.ArgumentNull("request");
} ExceptionDispatchInfo exceptionInfo;
HttpControllerContext controllerContext = null; try
{
//1.通过IHttpControllerSelector获取HttpControllerDescriptor
HttpControllerDescriptor controllerDescriptor = ControllerSelector.SelectController(request);
if (controllerDescriptor == null)
{
return request.CreateErrorResponse(
HttpStatusCode.NotFound,
Error.Format(SRResources.ResourceNotFound, request.RequestUri),
SRResources.NoControllerSelected);
}
//2.HttpControllerDescriptor的CreateController方法创建出控制器实例
IHttpController controller = controllerDescriptor.CreateController(request);
if (controller == null)
{
return request.CreateErrorResponse(
HttpStatusCode.NotFound,
Error.Format(SRResources.ResourceNotFound, request.RequestUri),
SRResources.NoControllerCreated);
}
//准备参数ControllerContext
controllerContext = CreateControllerContext(request, controllerDescriptor, controller);
//3.直接执行控制器的ExecuteAsync,即抽象类ApiController里的ExecuteAsync方法
return await controller.ExecuteAsync(controllerContext, cancellationToken);
}
catch (OperationCanceledException)
{
// Propogate the canceled task without calling exception loggers or handlers.
throw;
}
catch (HttpResponseException httpResponseException)
{
return httpResponseException.Response;
}
catch (Exception exception)
{
exceptionInfo = ExceptionDispatchInfo.Capture(exception);
} Debug.Assert(exceptionInfo.SourceException != null); ExceptionContext exceptionContext = new ExceptionContext(
exceptionInfo.SourceException,
ExceptionCatchBlocks.HttpControllerDispatcher,
request)
{
ControllerContext = controllerContext,
}; await ExceptionLogger.LogAsync(exceptionContext, cancellationToken);
HttpResponseMessage response = await ExceptionHandler.HandleAsync(exceptionContext, cancellationToken); if (response == null)
{
exceptionInfo.Throw();
} return response;
} private static HttpControllerContext CreateControllerContext(
HttpRequestMessage request,
HttpControllerDescriptor controllerDescriptor,
IHttpController controller)
{
Contract.Assert(request != null);
Contract.Assert(controllerDescriptor != null);
Contract.Assert(controller != null); HttpConfiguration controllerConfiguration = controllerDescriptor.Configuration; // Set the controller configuration on the request properties
HttpConfiguration requestConfig = request.GetConfiguration();
if (requestConfig == null)
{
request.SetConfiguration(controllerConfiguration);
}
else
{
if (requestConfig != controllerConfiguration)
{
request.SetConfiguration(controllerConfiguration);
}
} HttpRequestContext requestContext = request.GetRequestContext(); // if the host doesn't create the context we will fallback to creating it.
if (requestContext == null)
{
requestContext = new RequestBackedHttpRequestContext(request)
{
// we are caching controller configuration to support per controller configuration.
Configuration = controllerConfiguration,
}; // if the host did not set a request context we will also set it back to the request.
request.SetRequestContext(requestContext);
} return new HttpControllerContext(requestContext, request, controllerDescriptor, controller);
} private static HttpConfiguration EnsureNonNull(HttpConfiguration configuration)
{
if (configuration == null)
{
throw Error.ArgumentNull("configuration");
} return configuration;
}
}

  从SendAsync方法可以知道,主要有三大关键代码:

  1、通过IHttpControllerSelector获取HttpControllerDescriptor
  HttpControllerDescriptor controllerDescriptor = ControllerSelector.SelectController(request);

  ControllerSelector是从服务容器里获取的默认实现DefaultHttpControllerSelector,回顾下里边的代码:

  

  由Lazy特点,触发InitializeControllerInfoCache方法

  

  

  进入HttpControllerTypeCache,读取缓存,由Lazy特点,触发InitializeCache

  

  通过AssemblieResolver和HttpControllerTypeResolver组件构建出合法的控制器类型列表

  

  执行HttpControllerTypeCache获取Cache后,根据其构建出控制器描述符缓存,SelectController方法直接从该缓存中获取最后的控制器描述符

  2、HttpControllerDescriptor的CreateController方法创建出控制器实例

   IHttpController controller = controllerDescriptor.CreateController(request);

  使用HttpControllerDescriptor的CreateController方法创建

  

  内部调用了组件DefaultHttpControllerActivator实现

  

        

       

  3、直接执行控制器实例的ExecuteAsync,即抽象类ApiController里的ExecuteAsync方法

  //准备参数ControllerContext
  controllerContext = CreateControllerContext(request, controllerDescriptor, controller);
  return await controller.ExecuteAsync(controllerContext, cancellationToken);

  到这里就进入ApiController 的ExecuteAsync

//主要方法,创建控制器对象后,会调用ExecuteAsync方法,进行后续操作,由于还没讲控制器的创建,里边的逻辑以后再细说
public virtual Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken)
{
if (_initialized)
{
// 如果已经创建过该实例,就抛出异常,一个控制器实例,多次请求不能重复使用
throw Error.InvalidOperation(SRResources.CannotSupportSingletonInstance, typeof(ApiController).Name, typeof(IHttpControllerActivator).Name);
} Initialize(controllerContext); if (Request != null)
{
//先注册到待销毁集合,待请求完成后一起销毁改控制器实例
Request.RegisterForDispose(this);
} HttpControllerDescriptor controllerDescriptor = controllerContext.ControllerDescriptor;
ServicesContainer controllerServices = controllerDescriptor.Configuration.Services;
//选择Action
HttpActionDescriptor actionDescriptor = controllerServices.GetActionSelector().SelectAction(controllerContext);
ActionContext.ActionDescriptor = actionDescriptor;
if (Request != null)
{
Request.SetActionDescriptor(actionDescriptor);
} FilterGrouping filterGrouping = actionDescriptor.GetFilterGrouping(); //ActionFilters
IActionFilter[] actionFilters = filterGrouping.ActionFilters;
//身份认证过滤器
IAuthenticationFilter[] authenticationFilters = filterGrouping.AuthenticationFilters;
//授权过滤器
IAuthorizationFilter[] authorizationFilters = filterGrouping.AuthorizationFilters;
//ExceptionFilters
IExceptionFilter[] exceptionFilters = filterGrouping.ExceptionFilters; IHttpActionResult result = new ActionFilterResult(actionDescriptor.ActionBinding, ActionContext,
controllerServices, actionFilters);
if (authorizationFilters.Length > )
{
result = new AuthorizationFilterResult(ActionContext, authorizationFilters, result);
}
if (authenticationFilters.Length > )
{
result = new AuthenticationFilterResult(ActionContext, this, authenticationFilters, result);
}
if (exceptionFilters.Length > )
{
IExceptionLogger exceptionLogger = ExceptionServices.GetLogger(controllerServices);
IExceptionHandler exceptionHandler = ExceptionServices.GetHandler(controllerServices);
result = new ExceptionFilterResult(ActionContext, exceptionFilters, exceptionLogger, exceptionHandler,
result);
}
//执行IHttpActionResult的ExecuteAsync
return result.ExecuteAsync(cancellationToken);
}

ASP.NET Web API 框架研究 Controller创建过程与消息处理管道的更多相关文章

  1. ASP.NET Web API 框架研究 Controller创建 HttpController介绍

    对请求进行路由解析以及消息处理管道进行处理后,最后可以从HttpRequestMessage对象的属性字典中获取解析的路由数据,后边我们就可以根据其进行HttpController的创建,从前边几篇可 ...

  2. ASP.NET Web API 框架研究 Controller创建 HttpController 类型解析 选择 创建

    上一篇介绍了HttpController的一些细节,接下来说下HttpController 类型解析.选择和创建.生产HttpController实例的生产线如下图: 一.涉及的类及源码分析 涉及的类 ...

  3. ASP.NET Web API 框架研究 Controller实例的销毁

    我们知道项目中创建的Controller,如ProductController都继承自ApiController抽象类,其又实现了接口IDisposable,所以,框架中自动调用Dispose方法来释 ...

  4. ASP.NET Web API 框架研究 ASP.NET Web API 路由

    ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...

  5. ASP.NET Web API 框架研究 Action方法介绍

    在根据请求解析出匹配的Controller类型并创建实例后,要在该Controller类型中的众多Action方法中选择与请求匹配的那一个,并执行,然后返回响应. Action方法,其元数据,主要包括 ...

  6. ASP.NET Web API 框架研究 核心的消息处理管道

    ASP.NET Web API 的核心框架是一个由一组HttpMessageHandler有序组成的双工消息处理管道:寄宿监听到请求接受后,把消息传入该管道经过所有HttpMessageHandler ...

  7. ASP.NET Web API 框架研究 IoC容器 DependencyResolver

    一.概念 1.IoC(Inversion of Control),控制反转 即将依赖对象的创建和维护交给一个外部容器来负责,而不是应用本身.如,在类型A中需要使用类型B的实例,而B的实例的创建不是由A ...

  8. ASP.NET Web API 框架研究 服务容器 ServicesContainer

    ServicesContainer是一个服务的容器,可以理解为—个轻量级的IoC容器,其维护着一个服务接口类型与服务实例之间的映射关系,可以根据服务接口类型获取对应的服务实例.构成ASP.NET We ...

  9. ASP.NET Web API 框架研究 Self Host模式下的消息处理管道

    Self Host模式下的ASP.NET Web API与WCF非常相似,都可以寄宿在任意类型的托管应用程序中,宿主可以是Windows Form .WPF.控制台应用以及Windows Servic ...

随机推荐

  1. 在centos7上安装elasticSearch

    因为elasticsearch是用java编写的,所以需要先安装JDK: jdk1.8的安装:安装指导 elasticsearch的下载和安装 一.下载elasticSearch 1.下载地址: ht ...

  2. linux RCU锁机制分析

    openVswitch(OVS)源代码之linux RCU锁机制分析 分类: linux内核  |  标签: 云计算,openVswitch,linux内核,RCU锁机制  |  作者: yuzhih ...

  3. N! (大数,优化)

    Problem Description 输出N的阶乘.(注意时间限制150ms&&注意不能打表后输出) 打表的定义:在本地主机预先计算出了每个值对应的答案,并把输入和输出的映射直接写入 ...

  4. Next generation sequencing (NGS)二代测序数据预处理与分析

    二代测序原理: 1.DNA待测文库构建. 超声波把DNA打断成小片段,一般200--500bp,两端加上不同的接头2.Flowcell.一个flowcell,8个channel,很多接头3.桥式PCR ...

  5. Python中的类方法、实例方法、静态方法

    类方法 @classmethod 在python中使用较少,类方法传入的第一个参数是 cls,是类本身: 类方法可以通过类直接调用或者通过实例直接调用,但无论哪种调用方式,最左侧传入的参数一定是类本身 ...

  6. Creating Your Own PHP Helper Functions In Laravel

    By Hamza Ali LAST UPDATED AUG 26, 2018  12,669 104 Laravel provides us with many built-in helper fun ...

  7. XXE总结

    0x00 目录 0x01 XML基础 定义:一种标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言. XML文档结构包括XML声明.D ...

  8. vue 设置button disabled

    <button v-bind:disabled="dis" @click="alert">button</button> dis:'' ...

  9. 纯css导航栏下划线

    .nav-underline > *{/* 指定容器,里面可以是li.span等多样化的元素 */ display: inline-block; margin: -3px; padding: 1 ...

  10. PHP + Redis 队列实战

    环境 centos6.5 PHP5.3 Redis安装 #yum install redis 1.redis配置认证密码 #vi /etc/redis.conf requirepass mypass ...