.NET Core请求控制器Action方法正确匹配,但为何404?
【導讀】提前預祝各位端午節快樂。有時候我們會發現方法名稱都正確匹配,但就是找不到對應請求接口,所以本文我們來深入了解下何時會出現接口請求404的情況。
匹配控制器Action方法(404)
首先我們創建一個web api應用程序,我們給出如下示例控制器代碼
[ApiController] [Route("[controller]/[action]")] public?class?WeatherController?:?ControllerBase {[HttpGet]string?Get(){return?"Hello?World";} }當我們進行如上請求時會發現接口請求不到,這是為何呢?細心的你應該可能發現了,對于請求方法是私有,而不是公共的,當我們加上public就可以請求到了接口
匹配控制器Action方法本質
經過如上示例,那么對于Action方法的到底要滿足怎樣的定義才能夠不至于請求不到呢?接下來我們看看源碼怎么講。我們找到DefaultApplicationModelProvider類,在此類中有一個OnProvidersExecuting方法用來構建控制器和Action方法模型,當我們構建完畢所有滿足條件的控制器模型后,緊接著勢必會遍歷控制器模型去獲取對應控制器模型下的Action方法,這里只截取獲取Action方法片段,源碼如下:
foreach?(var?controllerType?in?context.ControllerTypes) {????//獲取控制器模型下的Action方法foreach?(var?methodInfo?in?controllerType.AsType().GetMethods()){var?actionModel?=?CreateActionModel(controllerType,?methodInfo);if?(actionModel?==?null){continue;}actionModel.Controller?=?controllerModel;controllerModel.Actions.Add(actionModel);????} }上述紅色標記則是創建Action模型的重點,我們繼續往下看到底滿足哪些條件才創建Action模型呢?
到了這個方法里面,我們找到了如何確定一個方法為Action方法的源頭,由于該方法有點長,這里我采用文字敘述來作為判斷邏輯,如下:
如上是從方法定義的角度來過濾而獲取Action方法,除此之外,我們請求方法的名稱還可以自定義,比如通過路由、ActionName特性指定,那么二者是否存在優先級呢?比如如下示例:
我們可以看到此時將以ActionName特性作為方法名稱。所以在上述過濾方法定義后開始構建方法模型,在此之后還會再做一步操作,那就是查找該方法是否通過ActionName特性標識,若存在則以ActionName特性標識給定的名稱作為請求方法名稱,否則以方法定義名稱為準,源碼如下:
var?actionModel?=?new?ActionModel(methodInfo,?attributes);AddRange(actionModel.Filters,?attributes.OfType<IFilterMetadata>());var?actionName?=?attributes.OfType<ActionNameAttribute>().FirstOrDefault(); if?(actionName?.Name?!=?null) {actionModel.ActionName?=?actionName.Name; } else {actionModel.ActionName?=?methodInfo.Name; }還沒完,若是將路由特性放到Action方法上,如下,此時請求接口應該是weather/get還是weather/get1呢?
此時若我們以weather/get1請求將出現404,還是以路由特性模板給定為準進行請求,但最終會將路由上Action方法名稱通過ActionName特性上的名稱賦值給Action模型中的ActionName進行覆蓋,源碼如下,所以上述我們得到的action名稱為get1,當然這么做沒有任何實際意義。
public?static?void?AddRouteValues( ControllerActionDescriptor?actionDescriptor, ControllerModel?controller,ActionModel?action) {foreach?(var?kvp?in?action.RouteValues){if?(!actionDescriptor.RouteValues.ContainsKey(kvp.Key)){actionDescriptor.RouteValues.Add(kvp.Key,?kvp.Value);}}if?(!actionDescriptor.RouteValues.ContainsKey("action")){actionDescriptor.RouteValues.Add("action",?action.ActionName????string.Empty);}if?(!actionDescriptor.RouteValues.ContainsKey("controller")){actionDescriptor.RouteValues.Add("controller",?controller.ControllerName);} }本文我們只是單獨針對查找Action方法名稱匹配問題做了進一步的探討,了解其本質。根據源碼分析,對Acion方法名稱指定會做以下3步操作:
第一:根據方法定義進行過濾篩選
第二:若方法通過AcionName特性標識則以其所給名稱為準,否則以方法名稱為準,最終賦值給ActionModel上的ActionName屬性
第三:將ActionModel上的ActionName值賦值給路由集合中的鍵Action
總結
以上是生活随笔為你收集整理的.NET Core请求控制器Action方法正确匹配,但为何404?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .Net Core Configurat
- 下一篇: .Net Core Configurat