bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

ASP.NETWebAPI控制器執行過程(一)-創新互聯

ASP.NET Web API 控制器執行過程(一)

目前成都創新互聯公司已為1000+的企業提供了網站建設、域名、網頁空間、網站托管、服務器托管、企業網站設計、淶水網站維護等服務,公司將堅持客戶導向、應用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協力一起成長,共同發展。

前言

前面兩篇講解了控制器的創建過程,只是從框架源碼的角度去簡單的了解,在控制器創建過后所執行的過程也是尤為重要的,本篇就來簡單的說明一下控制器在創建過后將會做哪些工作。

ASP.NET Web API 控制器執行過程

ASP.NET Web API 控制器執行過程(一)

ASP.NET Web API 控制器執行過程(二)

控制器執行過程

我們知道控制器的生成過程都是在HttpControllerDispatcher類型中來操作的,那我們要想知道控制器在創建過后執行操作的入口點也必須在HttpControllerDispatcher類型中才能發現。來看如下示例代碼:

代碼1-1

   privateTask<HttpResponseMessage>SendAsyncInternal(HttpRequestMessagerequest, CancellationTokencancellationToken)
   {
        IHttpRouteDatarouteData=request.GetRouteData();
        HttpControllerDescriptordescriptor=this.ControllerSelector.SelectController(request);     
        IHttpControllercontroller=descriptor.CreateController(request);    
        HttpConfigurationconfiguration=request.GetConfiguration();
        HttpControllerContextcontrollerContext=newHttpControllerContext(descriptor.Configuration, routeData, request) {
            Controller=controller,
            ControllerDescriptor=descriptor
        };
        returncontroller.ExecuteAsync(controllerContext, cancellationToken);
}

看過前面兩篇的朋友看到這里的代碼一定會很熟悉了,控制器的生成過程就包含在了其中,在代碼1-1中我們會看到HttpControllerContext類型,從它的名稱來看想必大家也都知道了它的作用,代表著進入控制器處理階段的邏輯上的上下文對象,并且封裝著一些很重要的信息。

HttpControllerContext控制器上下文

示例代碼1-2

publicclassHttpControllerContext
   {
        publicHttpControllerContext();
        publicHttpControllerContext(HttpConfigurationconfiguration, IHttpRouteDatarouteData, HttpRequestMessagerequest);
 
        publicHttpConfigurationConfiguration { get; set; }
        publicIHttpControllerController { get; set; }
        publicHttpControllerDescriptorControllerDescriptor { get; set; }
        publicHttpRequestMessageRequest { get; set; }
        publicIHttpRouteDataRouteData { get; set; }
}

結合代碼1-2和代碼1-1可以看到在HttpControllerContext類型中對HttpConfiguration類型的對象,它的重要性不用多說了,里面包含著很多配置信息以及存放基礎設施的容器對象,然后就是路由數據對象IHttpRouteData類型,以及最后的Http請求對象HttpRequestMessage類型的對象,并且在代碼1-1中對HttpControllerContext類型中的Controller和ControllerDescriptor屬性進行了賦值,Controller屬性對應的就是當前被創建好的控制器,而ControllerDescriptor屬性則是表示Controller屬性對應控制器的描述類型,現在回頭再看一下HttpControllerContext類型的對象就知道它里面包含的內容是有多重要了。

現在我們再回到代碼1-1中,最后我們看到是由IHttpController類型的變量controller調用方法ExecuteAsync()方法由此進入控制器中,一般控制器都是繼承自ApiController,我們就從ApiController類型來入手。

ApiController類型

示例代碼1-3

   publicabstractclassApiController : IHttpController, IDisposable
   {
        publicvirtualTask<System.Net.Http.HttpResponseMessage>ExecuteAsync(HttpControllerContextcontrollerContext, CancellationTokencancellationToken);
}

在代碼1-3中我們可以看到再ApiController類型中定義了ExecuteAsync()方法,ApiController為抽象類型,控制器的主要執行過程也就是都在ExecuteAsync()方法中,下面我看一下具體的實現,如下示例代碼。

代碼1-4

publicvirtualTask<HttpResponseMessage>ExecuteAsync(HttpControllerContextcontrollerContext, CancellationTokencancellationToken)
   {
        HttpControllerDescriptorcontrollerDescriptor=controllerContext.ControllerDescriptor;
        ServicesContainercontrollerServices=controllerDescriptor.Configuration.Services;
        HttpActionDescriptoractionDescriptor=controllerServices.GetActionSelector().SelectAction(controllerContext);
        HttpActionContextactionContext=newHttpActionContext(controllerContext, actionDescriptor);
        FilterGroupinggrouping=newFilterGrouping(actionDescriptor.GetFilterPipeline());
        IEnumerable<IActionFilter>actionFilters=grouping.ActionFilters;
        IEnumerable<IAuthorizationFilter>authorizationFilters=grouping.AuthorizationFilters;
        IEnumerable<IExceptionFilter>exceptionFilters=grouping.ExceptionFilters;
        returnInvokeActionWithExceptionFilters(InvokeActionWithAuthorizationFilters(actionContext, cancellationToken, authorizationFilters, ()=>actionDescriptor.ActionBinding.ExecuteBindingAsync(actionContext, cancellationToken).Then<HttpResponseMessage>(delegate {
            this._modelState=actionContext.ModelState;
            returnInvokeActionWithActionFilters(actionContext, cancellationToken, actionFilters, () =>controllerServices.GetActionInvoker().InvokeActionAsync(actionContext, cancellationToken))();
        }, newCancellationToken(), false))(), actionContext, cancellationToken, exceptionFilters);
}

代碼1-4中定義了控制器的執行過程,我們就從源碼的角度去了解一下控制器的執行過程。

在代碼1-4中先是從控制器上下文對象中獲取當前控制器類型的描述對象HttpControllerDescriptor類型的實例,而后從HttpControllerDescriptor類型實例從獲取在HttpConfiguration中的服務容器ServicesContainer類型的實例,對于這些類型前面的篇幅或多或少的講過了。

在這之后從服務容器中獲取IHttpActionSelector類型的行為選擇器并且經過篩選獲取到最佳匹配的HttpActionDescriptor類型,在之前也有講到過HttpControllerDescriptor,這里的HttpActionDescriptor跟其相似,就是表示控制其行為(方法)的元數據信息。

下面我就來講解一下控制器行為選擇器的執行過程,也就是它篩選方法的幾個步驟。

首先我們要知道控制器行為選擇器的類型,從代碼1-4中可以看到是通過服務容器對象的擴展方法來獲取的,在前面的篇幅也都講過了,這里可以得知我們要查看的控制器行為選擇器的類型就是ApiControllerActionSelector類型。

ApiControllerActionSelector控制器行為選擇器

示例代碼1-5

   publicclassApiControllerActionSelector : IHttpActionSelector
   {
        //Fields
        privatereadonlyobject_cacheKey;
        privateActionSelectorCacheItem_fastCache;
        privateconststringActionRouteKey="action";
        privateconststringControllerRouteKey="controller";
 
        //Methods
        publicApiControllerActionSelector();
        publicvirtualILookup<string, HttpActionDescriptor>GetActionMapping(HttpControllerDescriptorcontrollerDescriptor);
        privateActionSelectorCacheItemGetInternalSelector(HttpControllerDescriptorcontrollerDescriptor);
        publicvirtualHttpActionDescriptorSelectAction(HttpControllerContextcontrollerContext);
 
        //Nested Types
        privateclassActionSelectorCacheItem
        {
        }
 
        privateclassLookupAdapter : ILookup<string, HttpActionDescriptor>, IEnumerable<IGrouping<string, HttpActionDescriptor>>, IEnumerable
        {
        }
}

從代碼1-5中我們可以看到ApiControllerActionSelector類型中包含著兩個私有類,這兩個私有類后面會有講到起到的作用也很重要。

下面我們還是回到代碼1-4中的邏輯,從調用控制器行為選擇器中調用SelectAction()方法開始。

在ApiControllerActionSelector類型中調用SelectAction()時,實際是由SelectAction()方法調用GetInternalSelector()方法生成一個控制器方法的緩存對象,也就是ApiControllerActionSelector類型的私有類ActionSelectorCacheItem,而真正的篩選工作都是由它來執行的,所以下面才是介紹的重點。

控制器方法選擇器-篩選方法的步驟

1初始化篩選

在ActionSelectorCacheItem類型的初始化的時候, ActionSelectorCacheItem實例中會首先根據HttpControllerDescriptor對象獲取到控制器本身的類型,然后利用反射的技術根據條件獲取到當前控制器類型中的所有方法,最后保存為MethodInfo[]。而所謂的條件就是(BindingFlags.Public 、BindingFlags.Instance、方法所屬類型必須是ApiController類型的)。

我們看下ActionSelectorCacheItem類型中的字段信息,這些字段里存放的都是很重要的數據,后面會一一說明。

示例代碼1-6

        privatereadonlyReflectedHttpActionDescriptor[] _actionDescriptors;
        privatereadonlyILookup<string, ReflectedHttpActionDescriptor>_actionNameMapping;
        privatereadonlyIDictionary<ReflectedHttpActionDescriptor, string[]>_actionParameterNames=newDictionary<ReflectedHttpActionDescriptor, string[]>();
        privatereadonlyHttpMethod[] _cacheListVerbKinds=newHttpMethod[] { HttpMethod.Get, HttpMethod.Put, HttpMethod.Post };
        privatereadonlyReflectedHttpActionDescriptor[][] _cacheListVerbs;
        privatereadonlyHttpControllerDescriptor_controllerDescriptor;

1.1基礎信息初始化-ReflectedHttpActionDescriptor[] _actionDescriptors

這個時候初始化工作并沒有做完,這時候會把MethodInfo[]數組中的每個MethodInfo實例封裝成ReflectedHttpActionDescriptor類型的對象,對于類型稍后再說。在封裝成ReflectedHttpActionDescriptor類型的對象后,也會將每個實例存至一個ReflectedHttpActionDescriptor類型的數組中。

1.2 基礎信息初始化-IDictionary<ReflectedHttpActionDescriptor, string[]>_actionParameterNames

在1.1的工作做完之后呢,就會對每個ReflectedHttpActionDescriptor類型的對象進行分析,分析啥?分析方法的參數名稱,并且已1:n的方式存在IDictionary<ReflectedHttpActionDescriptor, string[]>類型的鍵值隊中。這里存放的值就是一個方法描述對象作為key值,value值是這個方法的所有參數名稱。

1.3 基礎信息初始化-ILookup<string, ReflectedHttpActionDescriptor> _actionNameMapping

這里的工作是根據1.1工作的結果,利用_actionDescriptors變量來根據ActionName分組,而最后_actionNameMapping中的值也是集合類型,不過每一項中的值都是個1:n的鍵值隊值。因為控制器方法可能存在重載的情況。

1.4 基礎信息初始化-ReflectedHttpActionDescriptor[][]_cacheListVerbs

_cacheListVerbs值的初始化在最后,它的定義是一個二維數組,數組初始確定為三行N列,三行的控制是由_cacheListVerbKinds值控制的,這里初始化的是根據1.1工作的結果將_actionDescriptors值按Http方法類型進行分類,所以我說的是三行N列。

上面的這些步驟雖然有點煩,不過了解一下便于下面的理解。

2. Action名稱篩選

示例代碼1-7

public HttpActionDescriptor SelectAction(HttpControllerContext controllerContext)

在ActionSelectorCacheItem類型的SelectAction()方法中,將會進行剩下的幾個篩選步驟,首先是會從方法的參數controllerContext中獲取到路由數據對象,并且在其Values屬性中查詢是否有“Action”鍵對應的方法名稱值,這個時候就會出現下面兩種情況。

2.1如果注冊的路由中有Action名稱

這這種情況下會把上面1.3中的工作成果拿來,_actionNameMapping根據Action名稱獲取到一個ReflectedHttpActionDescriptor類型的數組,這個數組在整個流程中還不能往下走,還要經過篩選,篩選的規則是判斷ReflectedHttpActionDescriptor中支持的Http方法類型是否支持當前請求的Http方法類型。

這里就涉及到在ReflectedHttpActionDescriptor類型的內部對IActionHttpMethodProvider類型特性的處理,不多說后面的文章會講到。這里上一張圖大家先留個印象。

圖1

ASP.NET Web API 控制器執行過程(一)

2.2沒有路由名稱的根據Http方法類型

在這種情況下,則是根據代碼1-7中的方法的方法參數controllerContext中獲取當前的請求類型,然后從1.4的工作結果中用_cacheListVerbs值根據當前請求的Http方法類型獲取到ReflectedHttpActionDescriptor類型的數組實例。

3.根據請求參數名稱、數量來匹配

3.1有參數的情況下

在這種情況下,會先把路由數據對象的Values屬性中的Keys值存放在一個集合A中,然后再獲取當前請求的查詢字符串集合,并且把集合中的所有Key值添加到集合A中,這就使的所有請求的參數名稱都在一個集合中,然后就會從1.2的結果中根據當前的ReflectedHttpActionDescriptor類型實例(這里是接著2的流程,所以這里是ReflectedHttpActionDescriptor類型的數組遍歷執行)從_actionParameterNames獲取對應的參數名稱數組,然后是集合A會和獲取的參數名稱數組做一一的比較,看看集合A中是否包含參數名稱,如果都有了則是滿足條件。

這里返回的依然可能是ReflectedHttpActionDescriptor類型的數組,因為在一個方法有重載時,比如說Get(stringa)和Get(string a,string b)兩個方法時,請求中如果有a和b兩個參數的話,Get(string a)也是滿足條件的。

3.2無參數的情況下

這種情況下就比較簡單了,從1.2的結果中還如上述那般,遍歷的根據ReflectedHttpActionDescriptor類型實例獲取參數名稱數組,找到數組長度為0的。

4. 排除IActionMethodSelector類型特性的控制器方法

到最后一個篩選條件了,還是遍歷ReflectedHttpActionDescriptor類型數組中的每一項,并且查找他們是否有使用實現了IActionMethodSelector接口的特性。

4.1有使用了實現IActionMethodSelector接口的特性

在這種情況下,會獲取到IActionMethodSelector類型,并且調用其實現方法IsValidForRequest(),如果返回true的話這個ReflectedHttpActionDescriptor類型才可以被使用,這也是提供給我們自定義實現的一個便捷,通常情況下是下面的這種情況。

4.2沒有使用實現IActionMethodSelector接口的特性

在這種情況下,會添加ReflectedHttpActionDescriptor類型到返回實例的集合中。

最后控制器行為選擇器只會返回ReflectedHttpActionDescriptor類型集合的中的第一項且必須是只有一項,其他情況都會拋出異常。

這個時候思緒回到代碼1-4,看到HttpActionDescriptor(ReflectedHttpActionDescriptor)類型變量被賦值,回想下上面的過程,感覺過了好久一樣。

最后貼一下很粗略的示意圖

圖2

ASP.NET Web API 控制器執行過程(一)

我們上面所講的也不過只是在整個過程中的第一步過程。

另外有需要云服務器可以了解下創新互聯scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業上云的綜合解決方案,具有“安全穩定、簡單易用、服務可用性高、性價比高”等特點與優勢,專為企業上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

分享名稱:ASP.NETWebAPI控制器執行過程(一)-創新互聯
網頁地址:http://vcdvsql.cn/article10/cssogo.html

成都網站建設公司_創新互聯,為您提供全網營銷推廣用戶體驗網站維護定制開發網站排名標簽優化

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

h5響應式網站建設