WebApi 2中OData控制器http请求的完整生命周期是什么

Joh*_*lip 9 asp.net iis odata asp.net-web-api

我想知道在IIS中托管的ODataController上,odata http请求的完整生命周期是什么.

例如:

  • IIS流水线步骤有哪些?
  • 进入ASP.NET控制器区域时如何处理请求?
  • 何时应用路由?
  • 当这样的属性HttpPost,ApplyFilter被应用?

MrM*_*ins 7

也许这个线程可以帮助你: 43个简单步骤中的ASP.NET Web API 2 HTTP消息生命周期

这一切都始于IIS: 在此输入图像描述

  1. IIS(或OWIN自托管)接收请求.
  2. 然后将请求传递给HttpServer的实例. 在此输入图像描述

  3. HttpServer负责调度HttpRequestMessage对象.

  4. HttpRequestMessage提供对请求的强类型访问. 在此输入图像描述

  5. 如果管道上存在DelegatingHandler的一个或多个全局实例,则将请求传递给它.请求按照所述实例添加到管道的顺序到达DelegatingHandler的实例.

DelegatingHandler实例可以跳过管道的其余部分并创建自己的响应.我在我的自定义验证与FluentValidation帖子中完成了这一点.

  1. 如果HttpRequestMessage传递DelegatingHandler实例(或者不存在此类处理程序),则请求将进入HttpRoutingDispatcher实例.

HttpRoutingDispatcher根据匹配的路由选择要调用的路由处理程序.如果不存在这样的路由(例如,Route.Handler为null,如图所示),则请求直接进入步骤10. 在此输入图像描述

  1. 如果给定路由存在路由处理程序,则将HttpRequestMessage发送到该处理程序.
  2. 可以将DelegatingHandler的实例附加到各个路由.如果存在这样的处理程序,则请求发送给它们(按照它们被添加到管道的顺序).
  3. 然后,HttpMessageHandler的一个实例处理请求.如果您提供自定义HttpMessageHandler,则所述处理程序可以选择将请求返回到"主"路径或自定义端点. 在此输入图像描述
  4. 该请求由HttpControllerDispatcher的实例接收,该实例将请求路由到由请求的URL确定的适当路由. 在此输入图像描述
  5. HttpControllerDispatcher选择适当的控制器来将请求路由到.
  6. IHttpControllerSelector的一个实例为给定的HttpMessage选择适当的HttpControllerDescriptor.
  7. IHttpControllerSelector调用IHttpControllerTypeResolver的一个实例,它最终将调用...
  8. IAssembliesResolver的一个实例,它最终选择适当的控制器并从步骤11返回到HttpControllerDispatcher.注意:如果实现依赖注入,IAssembliesResolver将被您注册的任何容器替换.
  9. 一旦HttpControllerDispatcher具有对相应控制器的引用,它就会调用IHttpControllerActivator上的Create()方法......
  10. 它创建实际的控制器并将其返回给Dispatcher.然后,调度程序将请求发送到Select Controller Action例程,如下所示. 在此输入图像描述 在此输入图像描述
  11. 我们现在有一个ApiController实例,它代表请求路由到的实际控制器类.所述实例调用IHttpActionSelector上的SelectAction()方法...
  12. 返回表示需要调用的操作的HttpActionDescriptor实例. 在此输入图像描述
  13. 一旦管道确定了将请求路由到哪个操作,它就会执行插入管道的任何验证过滤器(全局或本地调用的操作).这些过滤器允许您在整个应用程序中对单个操作,整个控制器或全局的请求进行身份验证.存在的任何过滤器都按照它们添加到管道的顺序执行(首先是全局过滤器,然后是控制器级过滤器,然后是动作级过滤器).
  14. 然后,请求进入[授权过滤器]层,其中存在的任何授权过滤器都应用于请求.授权过滤器可以选择创建自己的响应并将其发回,而不是允许请求继续通过管道.这些过滤器的应用方式与身份验证过滤器(全局,控制器级别,操作级别)相同.请注意,授权过滤器只能用于请求,而不能用于响应,因为假设存在响应,用户有权生成响应.
  15. 该请求现在进入模型绑定过程,该过程显示在主海报的下一部分中.操作所需的每个参数可以通过三个单独路径之一绑定到其值.绑定系统使用哪条路径取决于请求中所需值的位置. 在此输入图像描述
  16. 如果实体主体中存在操作参数值所需的数据,则Web API将读取请求的主体; FormatterParameterBinding的一个实例将调用相应的格式化程序类...
  17. 将值绑定到媒体类型(使用MediaTypeFormatter)...
  18. 这导致了一种新的复杂类型.
  19. 如果URL或查询字符串中存在参数值所需的数据,则所述URL将传递到IModelBinder的实例,该实例使用IValueProvider将值映射到模型(有关此主题的信息,请参阅Phil Haack的帖子以获取更多信息)... .
  20. 这导致一个简单的类型.
  21. 如果存在自定义HttpParameterBinding,系统将使用该自定义绑定来构建值...
  22. 这导致任何类型(简单或复杂)的对象都可以映射(参见Mike Stall关于这个主题的精彩系列). 在此输入图像描述
  23. 现在请求已绑定到模型,它将通过管道中可能存在的任何操作过滤器传递(全局或仅用于正在调用的操作).
  24. 传递操作过滤器后,将调用操作本身,系统将等待响应. 在此输入图像描述
  25. 如果操作产生异常并且存在异常过滤器,则异常过滤器将接收并处理异常.
  26. 如果没有发生异常,则该操作通过运行结果转换子例程生成HttpResponseMessage的实例,如下一屏幕截图所示. 在此输入图像描述
  27. 如果返回类型已经是HttpResponseMessage,我们不需要进行任何转换,因此传递返回值.
  28. 如果返回类型为void,.NET将返回状态为204 No Content的HttpResponseMessage.
  29. 如果返回类型是IHttpActionResult,则调用方法ExecuteAsync来创建HttpResponseMessage.在任何使用return Ok()的Web API方法中; 或返回BadRequest(); 或类似的东西,返回语句遵循此过程,而不是任何其他进程,因为这些操作的返回类型是IHttpActionResult.
  30. 对于所有其他类型,.NET将创建一个HttpResponseMessage,并将返回的序列化值放在该消息的正文中.
  31. 创建HttpResponseMessage后,将其返回到主管道. 在此输入图像描述
  32. 将新创建的HttpResponseMessage传递给可能存在的任何AuthenticationFilters. 在此输入图像描述
  33. HttpResponseMessage流经HttpControllerDispatcher,此时可能不会对它做任何事情.
  34. 响应也流经HttpRoutingDispatcher,它再也不会对它做任何事情.
  35. 响应现在通过设置为处理它的任何DelegatingHandler继续.此时,DelegatingHandler对象实际上只能更改正在发送的响应(例如,拦截某些响应并更改为适当的HTTP状态). 在此输入图像描述
  36. 最终的HttpResponseMessage被赋予HttpServer实例.
  37. 它返回一个Http响应给调用客户端


Roh*_*ith 6

查看源代码,ODataController是另一个控制器,它继承自 ApiController,具有自定义路由和格式。所以我想所有应用于 ApiController 的逻辑也适用于它。它还具有自定义格式和自定义路由,使用ODataFormattingODataRouting

什么是 IIS 流水线步骤?

IIS 流水线步骤与任何其他 mvc 控制器相同。本质上,我们拥有构成流水线的所有 http 模块和处理程序。更多详细信息可以在asp.net 应用程序生命周期中找到。从这条线来看,当 mvc 请求来自 URLRoutingModule 时,MvcRouteHandler 和 Mvchandler 协同工作来为 MVC 请求提供服务。下一个问题详细解释。

进入 ASP.NET 控制器区域时如何处理请求?什么时候应用路由?

一切都从一个 ODataController 开始。几乎 MVC 中的一切都是可扩展的(asp.net mvc 中的 13 个扩展点),你命名它,所有这些点都为 OData 扩展。例如从自定义控制器开始,我们有

  • 来自IHttpActionSelector 的自定义 ODataActionSelector 。您可以在此处找到示例实现
  • IActionValueBinder,示例实现在这里
  • 内容协商器
  • 等等诸如此类。

    /// 为支持使用 OData 格式写入和读取数据的 OData 控制器定义基类

    /// </summary>
    [ODataFormatting]
    [ODataRouting]
    [ApiExplorerSettings(IgnoreApi = true)]
    public abstract class ODataController : ApiController
    
    Run Code Online (Sandbox Code Playgroud)
    1. 接收应用程序的第一个请求 -> 在 Global.asax 文件中,Route 对象被添加到 RouteTable 对象中。
    2. 执行路由 -> UrlRoutingModule 模块使用 RouteTable 集合中第一个匹配的 Route 对象。从 ODataRouting 中,将路由添加到 RouteTable 集合中。
    3. 创建MVC请求处理程序-> MvcRouteHandler对象创建一个MvcHandler类的实例,并将RequestContext实例传递给处理程序
    4. 创建控制器 -> MvcHandler 对象使用 RequestContext 实例来标识 IControllerFactory 对象来创建控制器实例
    5. 执行控制器 -> MvcHandler 实例调用控制器的 Execute 方法
    6. Invoke action -> 对于继承自ControllerBase类的控制器,与控制器关联的ControllerActionInvoker对象决定调用控制器类的哪个action方法,然后调用那个方法 7.Action返回所有自定义的CreatedODataResult,UpdatedODataResult等
    7. 为 ODATA 注册了自定义 ODataMediaTypeFormatter 以格式化数据。