ASP.NET Web API WebHost宿主环境中管道、路由

简介:

ASP.NET Web API WebHost宿主环境中管道、路由


前言

上篇中说到ASP.NET Web API框架在SelfHost环境中管道、路由的一个形态,本篇就来说明一下在WebHost环境中ASP.NET Web API框架中的管道、路由又是哪一种形态。

 

ASP.NET Web API路由、管道

  • ASP.NET Web API 开篇介绍示例

  • ASP.NET Web API 路由对象介绍

  • ASP.NET Web API 管道模型

  • ASP.NET Web API selfhost宿主环境中管道、路由

  • ASP.NET Web API webhost宿主环境中管道、路由

 

ASP.NET Web API webhost宿主环境中管道、路由

下面将会主要讲解路由的注册执行过程(WebHost环境),对于管道不会去刻意的说明,都会包含在路由的讲解中,拆开来说明效果不太好。

 

HttpRoute->HostedHttpRoute->HttpWebRoute->Route

想要清楚的了解路由的执行过程以及管道的形态,就必须对路由对象熟知,然而在前面的《ASP.NET Web API 路由对象介绍》篇幅中只是分别的对各个环境下的路由对象类型进行了说明,并没有说明转变的过程。

现在就来讲解路由对象的“转变”过程。

示例代码1-1

1
2
3
4
5
         protected  void  Application_Start( object  sender, EventArgs e)
         {
             GlobalConfiguration.Configuration.Routes.MapHttpRoute(
               "DefaultAPI" "api/{controller}/{id}" new  { controller= "product" ,id = RouteParameter.Optional });
         }

示例代码1-1中是在WebHost环境下进行的路由注册,根据MapHttpRoute()方法我们转定义过去应该是一个HttpRouteCollection类型的扩展方法类型HttpRouteCollectionExtensions,既然是HttpRouteCollectionExtensions类型里的实现那我们就过去看看到底啥情况。

示例代码1-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public  static  IHttpRoute MapHttpRoute( this  HttpRouteCollection routes,  string  name,  string  routeTemplate,  object  defaults,  object  constraints, HttpMessageHandler handler)
         {
             if  (routes ==  null )
             {
                 throw  System.Web.Http.Error.ArgumentNull( "routes" );
             }
             HttpRouteValueDictionary dictionary =  new  HttpRouteValueDictionary(defaults);
             HttpRouteValueDictionary dictionary2 =  new  HttpRouteValueDictionary(constraints);
             IDictionary< string object > dataTokens =  null ;
             HttpMessageHandler handler2 = handler;
             IHttpRoute route = routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2);
             routes.Add(name, route);
             return  route;
         }

我们可以看到返回类型是IHttpRoute,生成则是由HttpRouteCollection类型的实例调用其中的CreateRoute()方法来实现,这里有的朋友要问了,这不是SelfHost中的路由注册实现方式吗?回答是对的,只不过在WebHost中利用多态来实现返回成其他的类型,接着往下看。

既然都看到了在这里发生的变化,那说明是有继承了HttpRouteCollection类型的这么一个类型然后创建的路由对象。这样一理就清晰多了,在SelfHost环境中HttpRouteCollection类型是存在于HttpConfiguration类型的对象中,并不单独使用。而在WebHost中也是。

这个时候我们再回过头来看一下代码1-1中的GlobalConfiguration类型中的定义。

示例代码1-3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
         private  static  Lazy<HttpConfiguration> _configuration =  new  Lazy<HttpConfiguration>( delegate  {
             HttpConfiguration configuration =  new  HttpConfiguration( new  HostedHttpRouteCollection(RouteTable.Routes));
             configuration.Services.Replace( typeof (IAssembliesResolver),  new  WebHostAssembliesResolver());
             configuration.Services.Replace( typeof (IHttpControllerTypeResolver),  new  WebHostHttpControllerTypeResolver());
             configuration.Services.Replace( typeof (IHostBufferPolicySelector),  new  WebHostBufferPolicySelector());
             return  configuration;
         });
         public  static  HttpConfiguration Configuration
         {
             get
             {
                 return  _configuration.Value;
             }
         }

从代码1-3中我们可以看到_configuration静态变量使用了延迟加载,啥意思呢就是下面的那个HttpConfiguration类型的Configuration属性如果使用了才会去实例化,跑偏了这不是重点。

重点是在实例化静态变量_configuration中可以清楚的看到使用了HostedHttpRouteCollection类型的路由集合类型对象作为构造函数参数。可以自行的去看一下HostedHttpRouteCollection的内部结构。

现在再回到创建路由的那会,也就是代码1-1和代码1-2中所示的那样,实际也就是HostedHttpRouteCollection类型在创建路由对象,按照老规矩直接看实现代码。

示例代码1-4

1
2
3
4
public  override  IHttpRoute CreateRoute( string  uriTemplate, IDictionary< string object > defaults, IDictionary< string object > constraints, IDictionary< string object > dataTokens, HttpMessageHandler handler)
     {
         return  new  HostedHttpRoute(uriTemplate, defaults, constraints, dataTokens, handler);
     }

从代码1-4中可以清楚的看到是返回的是HostedHttpRoute路由对象,我们可以看一下构造函数,只有这样才能知道&ldquo;转变&rdquo;的过程。

1
2
3
4
5
6
7
8
         public  HostedHttpRoute( string  uriTemplate, IDictionary< string object > defaults, IDictionary< string object > constraints, IDictionary< string object > dataTokens, HttpMessageHandler handler)
     {
         RouteValueDictionary dictionary = (defaults !=  null ) ?  new  RouteValueDictionary(defaults) :  null ;
         RouteValueDictionary dictionary2 = (constraints !=  null ) ?  new  RouteValueDictionary(constraints) :  null ;
         RouteValueDictionary dictionary3 = (dataTokens !=  null ) ?  new  RouteValueDictionary(dataTokens) :  null ;
         this .OriginalRoute =  new  HttpWebRoute(uriTemplate, dictionary, dictionary2, dictionary3, HttpControllerRouteHandler.Instance,  this );
         this .Handler = handler;
    }

在代码1-4中我们只需要关注OriginalRoute属性的赋值,OriginalRoute属性是HostedHttpRoute类型里的一个属性,是用来设置对Route对象的引用,示例代码1-4中也就是HttpWebRoute类型的对象,对于HttpWebRoute对象的构造函数这里就不例举了。这个时候可以看到是将HttpControllerRouteHandler类型的对象作为Route(HttpWebRoute)对象的RouteHandler(路由处理程序)。

 

大家都知道ASP.NET Web API框架在WebHost环境中是依赖于ASP.NET的,实则也是通过IHttpModule来进行前期的消息拦截,下面我们看一下在HttpModule中的代码(我想应该是这样的,如果有误请指点。)

示例代码1-5

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
     public  class  WebAPIHttpModule:IHttpModule
     {
 
 
         public  void  Dispose()
         {
             throw  new  NotImplementedException();
         }
 
         public  void  Init(HttpApplication context)
         {
             context.PostResolveRequestCache += context_PostResolveRequestCache;
         }
 
         void  context_PostResolveRequestCache( object  sender, EventArgs e)
         {
             HttpApplication context = sender  as  HttpApplication;
             HttpContextWrapper contextWrapper =  new  HttpContextWrapper(context.Context);
             RouteData routeData = RouteTable.Routes.GetRouteData(contextWrapper);
             RequestContext requestContext= new  RequestContext(contextWrapper,routeData);
             IHttpHandler httpHandler = routeData.RouteHandler.GetHttpHandler(requestContext);
             IHttpAsyncHandler httpAsyncHandler = httpHandler  as  IHttpAsyncHandler;
             httpAsyncHandler.BeginProcessRequest(context.Context,  null null );
         }
      }

在代码1-5中我们可以看到首先是获取了RouteData对象实例,以此获取RouteHandler,然后根据RequestContext获取IHttpHandler,再转换为IHttpAsyncHandler类型的实例,然后调用其BeginProcessRequest()方法来执行操作。

上面这段话描述的是上述代码的执行过程,有的朋友可能会疑问了,怎么就获取RouteData了?

这里我给大家解释一下,在我们的代码1-2中,有这样的代码:

1
2
                         IHttpRoute route = routes.CreateRoute(routeTemplate, dictionary, dictionary2, dataTokens, handler2);
             routes.Add(name, route);

首先我们看第一句,这里的route上面说过了是HostedHttpRoute对象,这里毫无疑问直接过,然后我们再看第二句,这里的routes是HostedHttpRouteCollection对象不假,但是这个Add()方法添加的方向不是HostedHttpRouteCollection,而是由我们一开始在GlobalConfiguration类型中说过的RouteTable.Routes,当前环境是什么?ASP.NET框架环境对吧!毫无疑问这个Add()方法把上面所说的route(HostedHttpRoute对象)添加到了当前环境的RouteTable.Routes中,有的朋友会问了类型不对。确实是不对的在添加的时候route(HostedHttpRoute对象)会转换成HttpWebRoute对象,HttpWebRoute对象继承自Route,可以看前面的篇幅,想必说到这里大家应该明白了。这里我就不多说了。

 

我们接着回到代码1-5中,在获取了RouteData之后通过RouteHandler的GetHttphandler()方法获取IHttpHandler实例,在RouteData中的这个RouteHandler毫无疑问就是HttpControllerRouteHandler类型。

我们来看下HttpControllerRouteHandler类型中的GetHttphandler()方法:

1
2
3
4
     protected  virtual  IHttpHandler GetHttpHandler(RequestContext requestContext)
     {
         return  new  HttpControllerHandler(requestContext.RouteData);
     }

可以看到是由HttpControllerHandler这个对象类型来执行最后的操作,那我们就来看一下这个类型的定义:

1
public  class  HttpControllerHandler : IHttpAsyncHandler, IHttpHandler

现在大家明白为什么要转成IHttpAsyncHandler了吧,因为如果调用了实现了IHttpHandler接口的函数是会报出异常的,因为在HttpControllerHandler类型中并没有实现IHttpHandler接口只是一个空壳,然后我们再看一下HttpControllerHandler类型的静态构造函数:

图1

 这个_server是Lazy<HttpMessageInvoker>类型,在BeginProcessRequest()方法中会执行SendAsync()以此进入ASP.NET Web API的管道。

 下面我们看一下整体的一个示意图,

图2

 

最后对于HttpControllerDispatcher类型在控制器部分讲解。





     本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1536713,如需转载请自行联系原作者




相关文章
|
3月前
|
开发框架 .NET C#
ASP.NET Core Blazor 路由配置和导航
大家好,我是码农刚子。本文系统介绍Blazor单页应用的路由机制,涵盖基础配置、路由参数、编程式导航及高级功能。通过@page指令定义路由,支持参数约束、可选参数与通配符捕获,结合NavigationManager实现页面跳转与参数传递,并演示用户管理、产品展示等典型场景,全面掌握Blazor路由从入门到实战的完整方案。
357 6
|
4月前
|
安全 API 数据安全/隐私保护
【Azure 环境】Microsoft Graph API实现对Entra ID中应用生成密码的时间天数
本文介绍如何通过 Azure 的 App Management Policy 限制用户在创建 AAD 应用程序的 Client Secret 时设置最长 90 天的有效期。通过 Microsoft Graph API 配置 defaultAppManagementPolicy,可有效控制密码凭据的生命周期,增强安全管理。
156 4
|
开发框架 前端开发 JavaScript
ASP.NET Web Pages - 教程
ASP.NET Web Pages 是一种用于创建动态网页的开发模式,采用HTML、CSS、JavaScript 和服务器脚本。本教程聚焦于Web Pages,介绍如何使用Razor语法结合服务器端代码与前端技术,以及利用WebMatrix工具进行开发。适合初学者入门ASP.NET。
|
9月前
|
中间件 Go
Golang | Gin:net/http与Gin启动web服务的简单比较
总的来说,`net/http`和 `Gin`都是优秀的库,它们各有优缺点。你应该根据你的需求和经验来选择最适合你的工具。希望这个比较可以帮助你做出决策。
477 35
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
836 3
|
运维 前端开发 C#
一套以用户体验出发的.NET8 Web开源框架
一套以用户体验出发的.NET8 Web开源框架
352 7
一套以用户体验出发的.NET8 Web开源框架
|
开发框架 数据可视化 .NET
.NET 中管理 Web API 文档的两种方式
.NET 中管理 Web API 文档的两种方式
242 14
|
开发框架 .NET PHP
ASP.NET Web Pages - 添加 Razor 代码
ASP.NET Web Pages 使用 Razor 标记添加服务器端代码,支持 C# 和 Visual Basic。Razor 语法简洁易学,类似于 ASP 和 PHP。例如,在网页中加入 `@DateTime.Now` 可以实时显示当前时间。
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
315 9
|
缓存 监控 API
微服务架构下RESTful风格api实践中,我为何抛弃了路由参数 - 用简单设计来提速
本文探讨了 RESTful API 设计中的两种路径方案:动态路径和固定路径。动态路径通过路径参数实现资源的 CRUD 操作,而固定路径则通过查询参数和不同的 HTTP 方法实现相同功能。固定路径设计提高了安全性、路由匹配速度和 API 的可维护性,但也可能增加 URL 长度并降低表达灵活性。通过对比测试,固定路径在性能上表现更优,适合微服务架构下的 API 设计。
309 1