ASP.NET Web API 控制器创建过程(二)

简介:

ASP.NET Web API 控制器创建过程()

前言

本来这篇随笔应该是在上周就该写出来发布的,由于身体跟不上节奏感冒发烧有心无力,这种天气感冒发烧生不如死,也真正的体会到了什么叫病来如山倒,病去如抽丝。这两天状态才好了一点,让我理解了什么才是革命的本钱,希望大家也多保重身体。

好了,还是回归主题,对于上一篇的内容讲解的只是ASP.NET Web API控制器创建过程中的一个局部知识,在接着上篇内容讲解的之前,我会先回顾一下上篇的内容,并且在本篇里进行整合,让我们要看到的是一个整个的创建过程。

ASP.NET Web API 控制器创建、激活过程

l  ASP.NET Web API 控制器创建过程()

l  ASP.NET Web API 控制器创建过程()

 

创建、激活过程

1

wKioL1PxUgnw1q5JAAO-J5o25OE377.jpg

在前面的篇幅中我们说过APIController是由HttpControllerDispatcher类型来创建的,这只是表面上的,图1中显示的就是控制器创建的整个过程了,我们先来回顾一下上一篇所讲的,不然会觉得不连贯,在回顾的同时也会对图1进行讲解。

首先我们来分解图1,可以把图1中分为两个部分,

第一个部分就是HttpConfiguration类型所表示的部分。如图2

2

wKiom1PxUQ6BxiG-AAF_rzY-DJ8987.jpg

先来解释一下HttpConfiguration部分,在HttpConfiguration类型中有两个属性,第一个是ServicesContainer类型的属性Services,第二个就是IDependencyResolver类型的属性DependencyResolver,对于Services属性的类型在上篇中我也说过了,就是一个IoC容器,从HttpConfiguration类型角度来看就是一个依赖注入到HttpConfiguration中的IoC容器,对于DependencyResolver属性来说也差不多就是这个意思了。

只不过Services这个容器中存放的大多都是ASP.NET Web API框架中做一些基础工作的类型。

就好像上篇中说到的,在ASP.NET Web API框架中加载控制器所在程序集的时候我们就是使用自定义的工作项替换掉了Services容器中的默认工作项:

1
2
selfHostServer.Configuration.Services.Replace( typeof (IAssembliesResolver),
                    newCustomAssembliesResolver.LoadSpecifiedAssembliesResolver());

这里从图2中可以看出默认的DefaultAssembliesResolver类型来执行这项工作的。

到这里也就是上个篇幅中的主要内容了。下面我们还是继续分解图1,上面说了第一部分了下面来看第二部分,第二个部分就是HttpControllerDispatcher类型到APIController类型的生成过程,也就是图1了。

首先我们的ASP.NET Web API框架会从HttpConfiguration中的Services容器中获取一个ControllerSelector(控制器选择器),这个控制器选择器呢对应的类型大家从图2中也可以看到,图1中也有,很明了。

那么ControllerSelector主要干什么呢?肯定是选择控制器阿,当然了根据请求选择相应的控制器是主要功能,次要功能是啥?次要功能是生成控制器缓存,不然从哪选阿对不。在ASP.NET MVC框架中控制器缓存是存在xml文件中的,现在很好奇在ASP.NET Web API框架中控制器缓存是什么样的存储方式呢?

我们就来看一下控制器选择器次要功能

控制器选择器次要功能

首先我们先说明一下缓存的类型为ConcurrentDictionary<string, HttpControllerDescriptor>类型,就是一个一一对应的键值队,string表示着控制器名称,而HttpControllerDescriptor表示着对应控制器的控制器描述类型,这个类型很重要稍后再说,我们先要了解ConcurrentDictionary<string, HttpControllerDescriptor>缓存的由来。

首先在我们控制器选择器实例化的时候,在控制器选择器的构造函数中已经使用了延迟加载技术对控制器缓存进行了创建,具体的创建过程可以在图1看到,是由DefaultAssembliesResolver类型(或者是我们自定义的工作项)加载指定的程序集,并且交由DefaultHttpControllerTypeResolver类型根据ASP.NET Web API框架中默认的搜索过滤条件返回加载程序集中的所有符合条件的控制器类型(ControllerTypes),来看示例。

所用项目结构还是上个篇幅的示例:

3

wKiom1PxUVPDFd0SAAB4Da14LAw080.jpg

4

wKiom1PxUV2z2LplAAFRhEA66TI760.jpg

在图4中我们额外定义了一些控制器类型,然后在SelfHost端定义如下示例代码:

代码1-1

1
2
3
4
5
6
7
8
9
         staticvoidWriterControllerTypeMessage(HttpSelfHostServerselfHostServer)
         {
  
             ICollection<Type>types=selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver());
             foreach  (Typetypeintypes)
             {
                 Console.WriteLine(type.Namespace+ "_______" +type.Name);
             }
         }


并且在注册端调用此静态函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using  (HttpSelfHostServerselfHostServer=newHttpSelfHostServer(selfHostConfiguration))
             {
                 selfHostServer.Configuration.Routes.MapHttpRoute(
                     "DefaultApi" "api/{controller}/{id}" new  { id=RouteParameter.Optional });
  
                 selfHostServer.Configuration.Services.Replace( typeof (IAssembliesResolver),
                     newCustomAssembliesResolver.LoadSpecifiedAssembliesResolver());
  
  
                 WriterControllerTypeMessage(selfHostServer);
  
                 selfHostServer.OpenAsync();
                 Console.WriteLine( "服务器端服务监听已开启" );
                 Console.Read();
             }


结果如图5

5

wKiom1PxUXXDmUPEAAEjcnAu8us361.jpg

在我们获取了ControllerTypes过后了,ASP.NET Web API框架中有个HttpControllerTypeCache类型的对象就藏不住了,之前的一些操作都是由HttpControllerTypeCache类型去处理的,而在HttpControllerTypeCache获取了ControllerTypes过后就要做一个很重要的工作了,就是对ControllerTypes进行分组操作最后返回一个Dictionary<string, ILookup<string, Type>>类型的对象,就拿上面的示例来说吧,最后经过分组后的Dictionary<string, ILookup<string, Type>>类型值应该是:

Writer-->NameSpaceControllerOne->WriterController

      NameSpaceControllerTwo->WriterController

Read-->NameSpaceControllerOne->ReadController

WriterAndRead-->NameSpaceControllerThree->WriterAndReadController

Product-->WebAPIController->ProductController

这个时候的值并不是最终的缓存类型,而是通过我们的控制器选择器根据HttpControllerTypeCache类型所生成的Dictionary<string,ILookup<string, Type>>类型值来生成ConcurrentDictionary<string, HttpControllerDescriptor>缓存类型,还是根据上面的示例,我们看一下最后生成的缓存类型值。

修改1-1如下示例代码:

代码1-2

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
26
27
28
29
30
31
staticvoidWriterControllerTypeMessage(HttpSelfHostServerselfHostServer)
         {
  
             ICollection<Type>types=selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver());
             foreach  (Typetypeintypes)
             {
                 Console.WriteLine(type.Namespace+ "_______" +type.Name);
             }
  
  
  
             //Dictionary<string,ILookup<string, Type>> controllertypecache = types.GroupBy<Type,string>(t => t.Name,StringComparer.OrdinalIgnoreCase).ToDictionary<IGrouping<string,Type>, string, ILookup<string, Type>>
             //        (g => g.Key,
             //        g => g.ToLookup<Type,string>(t => (t.Namespace ?? string.Empty),StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase);
  
             //foreach(var value in controllertypecache)
             //{
             //    foreach (var val in value.Value)
             //    {
                    
             //    }
             //}
  
             IDictionary< string , HttpControllerDescriptor>mapping=selfHostServer.Configuration.Services.GetHttpControllerSelector().GetControllerMapping();
  
             foreach  (varmeginmapping)
             {
                 Console.WriteLine( "ControllerName:" +meg.Key+ ".ControllerTypeName:" +meg.Value.ControllerType.Name);
             }
  
         }


结果如图6

6

wKiom1PxUYzjIU-aAAGVFu9zCOw938.jpg

(在代码1-2中注释掉的部分就是可以查看对ControllerTypes进行分组操作返回Dictionary<string, ILookup<string, Type>>类型的值)。

控制器选择器主要功能

次要功能看完之后,主要功能想必大家也是很明了吧,在有了控制器缓存对象过后,控制器选择器则会根据HttpRequestMessage对象中的路由数据对象获取控制器名称,然后从缓存中获取到对应的HttpControllerDescriptor类型实例。

 

具体生成工作

在获取到了HttpControllerDescriptor类型实例过后生成IHttpController的工作就变得很简单了,还是从HttpConfiguration中的Services容器中获得对应的负责控制器生成激活的工作项,在图1中可以明确的看出是DefaultHttpControllerActivator类型,在DefaultHttpControllerActivator类型工作的时候它会从HttpConfiguration中获取DependencyResolver属性对应的容器,如果这里的情况不满足才会调用后面的TypeActivator来生成激活IHttpController(通过反射)






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




相关文章
|
2月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
60 4
|
2月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
166 3
|
27天前
|
开发框架 .NET 程序员
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
Autofac 是一个轻量级的依赖注入框架,专门为 .NET 应用程序量身定做,它就像是你代码中的 "魔法师",用它来管理对象的生命周期,让你的代码更加模块化、易于测试和维护
驾驭Autofac,ASP.NET WebApi实现依赖注入详细步骤总结
|
1月前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
53 1
|
1月前
|
JSON API 数据格式
如何使用Python和Flask构建一个简单的RESTful API。Flask是一个轻量级的Web框架
本文介绍了如何使用Python和Flask构建一个简单的RESTful API。Flask是一个轻量级的Web框架,适合小型项目和微服务。文章从环境准备、创建基本Flask应用、定义资源和路由、请求和响应处理、错误处理等方面进行了详细说明,并提供了示例代码。通过这些步骤,读者可以快速上手构建自己的RESTful API。
102 2
|
2月前
|
监控 负载均衡 API
Web、RESTful API 在微服务中有哪些作用?
在微服务架构中,Web 和 RESTful API 扮演着至关重要的角色。它们帮助实现服务之间的通信、数据交换和系统的可扩展性。
60 2
|
2月前
|
人工智能 搜索推荐 API
用于企业AI搜索的Bocha Web Search API,给LLM提供联网搜索能力和长文本上下文
博查Web Search API是由博查提供的企业级互联网网页搜索API接口,允许开发者通过编程访问博查搜索引擎的搜索结果和相关信息,实现在应用程序或网站中集成搜索功能。该API支持近亿级网页内容搜索,适用于各类AI应用、RAG应用和AI Agent智能体的开发,解决数据安全、价格高昂和内容合规等问题。通过注册博查开发者账户、获取API KEY并调用API,开发者可以轻松集成搜索功能。
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
109 9
|
2月前
|
存储 开发框架 .NET
.NET 8 实现无实体库表 API 部署服务
【10月更文挑战第12天】在.NET 8中,可通过以下步骤实现无实体库表的API部署:首先安装.NET 8 SDK及开发工具,并选用轻量级Web API框架如ASP.NET Core;接着创建新项目并设计API,利用内存数据结构模拟数据存储;最后配置项目设置并进行测试与部署。此方法适用于小型项目或临时解决方案,但对于大规模应用仍需考虑持久化存储以确保数据可靠性与可扩展性。
|
3月前
|
开发框架 监控 前端开发
在 ASP.NET Core Web API 中使用操作筛选器统一处理通用操作
【9月更文挑战第27天】操作筛选器是ASP.NET Core MVC和Web API中的一种过滤器,可在操作方法执行前后运行代码,适用于日志记录、性能监控和验证等场景。通过实现`IActionFilter`接口的`OnActionExecuting`和`OnActionExecuted`方法,可以统一处理日志、验证及异常。创建并注册自定义筛选器类,能提升代码的可维护性和复用性。