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表示著對應控制器的控制器描述型別,這個型別很重要稍後再說,我們先要了解ConcurrentDictionary快取的由來。
首先在我們控制器選擇器例項化的時候,在控制器選擇器的建構函式中已經使用了延遲載入技術對控制器快取進行了建立,具體的建立過程可以在圖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)
{
ICollectiontypes=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>型別的物件,就拿上面的示例來說吧,最後經過分組後的Dictionary>型別值應該是:
Writer-->NameSpaceControllerOne->WriterController
NameSpaceControllerTwo->WriterController
Read-->NameSpaceControllerOne->ReadController
WriterAndRead-->NameSpaceControllerThree->WriterAndReadController
Product-->WebAPIController->ProductController
這個時候的值並不是最終的快取型別,而是透過我們的控制器選擇器根據HttpControllerTypeCache型別所生成的Dictionary>型別值來生成ConcurrentDictionary快取型別,還是根據上面的示例,我們看一下最後生成的快取型別值。
修改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)
{
ICollectiontypes=selfHostServer.Configuration.Services.GetHttpControllerTypeResolver().GetControllerTypes(selfHostServer.Configuration.Services.GetAssembliesResolver());
foreach (Typetypeintypes)
{
Console.WriteLine(type.Namespace+"_______"+type.Name);
}
//Dictionary> controllertypecache = types.GroupBy(t => t.Name,StringComparer.OrdinalIgnoreCase).ToDictionary, string, ILookup>
// (g => g.Key,
// g => g.ToLookup(t => (t.Namespace ?? string.Empty),StringComparer.OrdinalIgnoreCase), StringComparer.OrdinalIgnoreCase);
//foreach(var value in controllertypecache)
//{
// foreach (var val in value.Value)
// {
// }
//}
IDictionarymapping=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>型別的值)。
控制器選擇器主要功能
次要功能看完之後,主要功能想必大家也是很明瞭吧,在有了控制器快取物件過後,控制器選擇器則會根據HttpRequestMessage物件中的路由資料物件獲取控制器名稱,然後從快取中獲取到對應的HttpControllerDescriptor型別例項。
具體生成工作
在獲取到了HttpControllerDescriptor型別例項過後生成IHttpController的工作就變得很簡單了,還是從HttpConfiguration中的Services容器中獲得對應的負責控制器生成啟用的工作項,在圖1中可以明確的看出是DefaultHttpControllerActivator型別,在DefaultHttpControllerActivator型別工作的時候它會從HttpConfiguration中獲取DependencyResolver屬性對應的容器,如果這裡的情況不滿足才會呼叫後面的TypeActivator來生成啟用IHttpController(透過反射)。
本來這篇隨筆應該是在上週就該寫出來釋出的,由於身體跟不上節奏感冒發燒有心無力,這種天氣感冒發燒生不如死,也真正的體會到了什麼叫病來如山倒,病去如抽絲。這兩天狀態才好了一點,讓我理解了什麼才是革命的本錢,希望大家也多保重身體。
好了,還是迴歸主題,對於上一篇的內容講解的只是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
首先在我們控制器選擇器例項化的時候,在控制器選擇器的建構函式中已經使用了延遲載入技術對控制器快取進行了建立,具體的建立過程可以在圖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
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
Writer-->NameSpaceControllerOne->WriterController
NameSpaceControllerTwo->WriterController
Read-->NameSpaceControllerOne->ReadController
WriterAndRead-->NameSpaceControllerThree->WriterAndReadController
Product-->WebAPIController->ProductController
這個時候的值並不是最終的快取型別,而是透過我們的控制器選擇器根據HttpControllerTypeCache型別所生成的Dictionary
修改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
foreach (Typetypeintypes)
{
Console.WriteLine(type.Namespace+"_______"+type.Name);
}
//Dictionary
// (g => g.Key,
// g => g.ToLookup
//foreach(var value in controllertypecache)
//{
// foreach (var val in value.Value)
// {
// }
//}
IDictionary
foreach (varmeginmapping)
{
Console.WriteLine("ControllerName:"+meg.Key+".ControllerTypeName:"+meg.Value.ControllerType.Name);
}
}
結果如圖6:
圖6
wKiom1PxUYzjIU-aAAGVFu9zCOw938.jpg
(在程式碼1-2中註釋掉的部分就是可以檢視對ControllerTypes進行分組操作返回Dictionary
控制器選擇器主要功能
次要功能看完之後,主要功能想必大家也是很明瞭吧,在有了控制器快取物件過後,控制器選擇器則會根據HttpRequestMessage物件中的路由資料物件獲取控制器名稱,然後從快取中獲取到對應的HttpControllerDescriptor型別例項。
具體生成工作
在獲取到了HttpControllerDescriptor型別例項過後生成IHttpController的工作就變得很簡單了,還是從HttpConfiguration中的Services容器中獲得對應的負責控制器生成啟用的工作項,在圖1中可以明確的看出是DefaultHttpControllerActivator型別,在DefaultHttpControllerActivator型別工作的時候它會從HttpConfiguration中獲取DependencyResolver屬性對應的容器,如果這裡的情況不滿足才會呼叫後面的TypeActivator來生成啟用IHttpController(透過反射)。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28904215/viewspace-1252970/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用 ASP.NET Core 和 MongoDB 建立 Web APIASP.NETMongoDBWebAPI
- .NET WEB API關鍵過程 思維導圖WebAPI
- ASP.NET Core Web API 與 SSLASP.NETWebAPI
- ASP.NET Core Web API 介面限流ASP.NETWebAPI
- ASP.NET Web API 中使用 swagger 來管理 API 文件ASP.NETWebAPISwagger
- ASP.NET Core Web API 整合測試ASP.NETWebAPI
- ASP.NET Core Web Api之JWT(一)ASP.NETWebAPIJWT
- ASP.NET Core Web API中使用SwaggerASP.NETWebAPISwagger
- 讓ASP.NET Web API的Action方法ASP.NETWebAPI
- ASP.NET Core Web API 教程 - Project ConfigurationASP.NETWebAPIProject
- 使用 ASP.NET Core MVC 建立 Web API——響應資料的內容協商(七)ASP.NETMVCWebAPI
- SAP Query建立過程
- [JVM]物件建立過程JVM物件
- Web請求過程Web
- 用ASP.NET Core 2.1 建立規範的 REST API -- 翻頁/排序/過濾等ASP.NETRESTAPI排序
- ASP.NET Core Web API 索引 (更新Redis in .NET Core)ASP.NETWebAPI索引Redis
- ASP.NET Core Web API 流式返回,逐字顯示ASP.NETWebAPI
- IoC在ASP.NET Web API中的應用ASP.NETWebAPI
- VS2022-建立 ASP.NET Core Web 應用ASP.NETWeb
- java類的建立過程Java
- 【ASP.NET Core】體驗一下 Mini Web APIASP.NETWebAPI
- 透過擴充套件讓ASP.NET Web API支援W3C的CORS規範套件ASP.NETWebAPICORS
- Spring建立Bean的過程DebugSpringBean
- mpls ldp lsp建立過程——VecloudCloud
- 用ASP.NET Core 2.1 建立規範的 REST API -- 保護API和其它ASP.NETRESTAPI
- 用ASP.NET Core 2.1 建立規範的 REST API -- HATEOASASP.NETRESTAPI
- ASP.NET Core Web API 整合測試中使用 Bearer TokenASP.NETWebAPI
- 針對ASP.NET Core Web API的先進架構ASP.NETWebAPI架構
- ASP.NET Core Web Api之JWT重新整理Token(三)ASP.NETWebAPIJWT
- ASP.NET Core Web Api之JWT VS Session VS Cookie(二)ASP.NETWebAPIJWTSessionCookie
- 舊 WCF 專案成功遷移到 asp.net core web apiASP.NETWebAPI
- 呼叫ASP.NET Web API不能傳送PUT/DELETE請求ASP.NETWebAPIdelete
- ASP.NET Core Web API + Angular 仿B站(二)後臺模型建立以及資料庫的初始化ASP.NETWebAPIAngular模型資料庫
- 通過Web API查詢資料WebAPI
- Netty NioEventLoop 建立過程原始碼分析NettyOOP原始碼
- JVM系列(三):JVM建立過程解析JVM
- laravel建立一個儲存過程Laravel儲存過程
- Asp.Net web api基於自定義Filter的安全認證ASP.NETWebAPIFilter
- asp.Net請求過程及管道中的事件ASP.NET事件