现在我们从代码角度来看下,从消息处理管道末尾是怎么创建出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. Luogu 1341 无序字母对 - 欧拉路径

    Solution 找一条字典序最小的欧拉路径. 用 $multiset$ 存储领接表. 欧拉路径模板传送门 Code #include<cstdio> #include<cstrin ...

  2. 201621123008 《Java程序设计》第十周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7-1回答 1.1 自己以前编写的代码中经常出现 ...

  3. lodash 中常用的方法

    odash是js集Array/Object/String/Function的Util于一身. lodash打包了Array/Object/String/Function里一些Api,好处是连ES6的也 ...

  4. nginx记录post数据日志

    1.vi nginx.conf 找到http {}中log_foramt ,定义post 日志格式 #log_format main '$remote_addr - $remote_user [$ti ...

  5. xgboost安装

    安装连接:https://www.zhihu.com/question/46377605 软件连接:https://www.lfd.uci.edu/~gohlke/pythonlibs/#xgboos ...

  6. Arithmetic Slices LT413

    A sequence of number is called arithmetic if it consists of at least three elements and if the diffe ...

  7. Java SE学习【一】

    学java也学了有1个多月了,算算时间,花在上面的时间应该是超过了100个小时了,现在的进度是变量.循环.分支.数组学完了,面向对象部分正在学.记录一下我在学习期间遇到的一些困惑与感想吧! 1.一开始 ...

  8. 关于 Web Api 2 认证与授权

    认证与授权 认证与授权,Authentication and Authorize,这个是两个不同的事.认证是对访问身份进行确认,如验证用户名和密码,而授权是在认证之后,判断是否具有权限进行某操作,如 ...

  9. spring学习九 spring aop详解

    本文来自于:https://www.cnblogs.com/jingzhishen/p/4980551.html AOP(Aspect-Oriented Programming,面向方面编程),可以说 ...

  10. 查看Android应用所需权限(uses-permission)

    http://www.tuicool.com/articles/zq2meq MainActivity如下: package cc.testusespermission; import android ...