.NET Core请求控制器Action方法正确匹配,但为何404?
【導(dǎo)讀】提前預(yù)祝各位端午節(jié)快樂。有時候我們會發(fā)現(xiàn)方法名稱都正確匹配,但就是找不到對應(yīng)請求接口,所以本文我們來深入了解下何時會出現(xiàn)接口請求404的情況。
匹配控制器Action方法(404)
首先我們創(chuàng)建一個web api應(yīng)用程序,我們給出如下示例控制器代碼
[ApiController] [Route("[controller]/[action]")] public?class?WeatherController?:?ControllerBase {[HttpGet]string?Get(){return?"Hello?World";} }當(dāng)我們進(jìn)行如上請求時會發(fā)現(xiàn)接口請求不到,這是為何呢?細(xì)心的你應(yīng)該可能發(fā)現(xiàn)了,對于請求方法是私有,而不是公共的,當(dāng)我們加上public就可以請求到了接口
匹配控制器Action方法本質(zhì)
經(jīng)過如上示例,那么對于Action方法的到底要滿足怎樣的定義才能夠不至于請求不到呢?接下來我們看看源碼怎么講。我們找到DefaultApplicationModelProvider類,在此類中有一個OnProvidersExecuting方法用來構(gòu)建控制器和Action方法模型,當(dāng)我們構(gòu)建完畢所有滿足條件的控制器模型后,緊接著勢必會遍歷控制器模型去獲取對應(yīng)控制器模型下的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);????} }上述紅色標(biāo)記則是創(chuàng)建Action模型的重點(diǎn),我們繼續(xù)往下看到底滿足哪些條件才創(chuàng)建Action模型呢?
到了這個方法里面,我們找到了如何確定一個方法為Action方法的源頭,由于該方法有點(diǎn)長,這里我采用文字?jǐn)⑹鰜碜鳛榕袛噙壿?#xff0c;如下:
如上是從方法定義的角度來過濾而獲取Action方法,除此之外,我們請求方法的名稱還可以自定義,比如通過路由、ActionName特性指定,那么二者是否存在優(yōu)先級呢?比如如下示例:
我們可以看到此時將以ActionName特性作為方法名稱。所以在上述過濾方法定義后開始構(gòu)建方法模型,在此之后還會再做一步操作,那就是查找該方法是否通過ActionName特性標(biāo)識,若存在則以ActionName特性標(biāo)識給定的名稱作為請求方法名稱,否則以方法定義名稱為準(zhǔn),源碼如下:
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方法上,如下,此時請求接口應(yīng)該是weather/get還是weather/get1呢?
此時若我們以weather/get1請求將出現(xiàn)404,還是以路由特性模板給定為準(zhǔn)進(jìn)行請求,但最終會將路由上Action方法名稱通過ActionName特性上的名稱賦值給Action模型中的ActionName進(jìn)行覆蓋,源碼如下,所以上述我們得到的action名稱為get1,當(dāng)然這么做沒有任何實(shí)際意義。
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);} }本文我們只是單獨(dú)針對查找Action方法名稱匹配問題做了進(jìn)一步的探討,了解其本質(zhì)。根據(jù)源碼分析,對Acion方法名稱指定會做以下3步操作:
第一:根據(jù)方法定義進(jìn)行過濾篩選
第二:若方法通過AcionName特性標(biāo)識則以其所給名稱為準(zhǔn),否則以方法名稱為準(zhǔn),最終賦值給ActionModel上的ActionName屬性
第三:將ActionModel上的ActionName值賦值給路由集合中的鍵Action
總結(jié)
以上是生活随笔為你收集整理的.NET Core请求控制器Action方法正确匹配,但为何404?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .Net Core Configurat
- 下一篇: .Net Core Configurat