標籤:
在WebAPI對於Action的選擇主要經過:Action方法名匹配,Http方法匹配,參數匹配三步。
Http方法匹配
WebAPI提供了三種Http方法的選擇方式,分別是:方法首碼,AcceptVerbs特性,HttpXXX特性
方法首碼:
在上一篇中都是採用的這種方式,即將Http方法作為Action的首碼。比如GetAll, PostByUrl。
另外這種方式只能指定一種Http方法,比如GetPutPostAll()只支援GET請求
AcceptVerbs特性
AcceptVerbs特性提供了兩個建構函式:
public AcceptVerbsAttribute(params string[] methods)
public AcceptVerbsAttribute(string method)
通過這兩個建構函式我們可以為Action的指定Http請求方式,比如:
[AcceptVerbs("POST","PUT")]
public IEnumerable<Figure> PostByBody([FromBody] Figure figure)
這個時候就可以採用Post,Put方式進行訪問。
HttpXXX特性
HttpXXX方式跟AcceptVerbs類似,我們可以將其看成是AcceptVerbs的防錯誤方式(在拼字http方法時可能會出現失誤),其格式如下:
[HttpPut]
[HttpPost]
public IEnumerable<Figure> PostByBody([FromBody] Figure figure)
ASP.NET WebAPI定義了7種對應的屬性類別型:
HttpGet
HttpHead
HttpPut
HttpPost
HttpPatch
HttpOptions
HttpDelete
如果採用了AcceptVerbs與HttpXXX方式,那麼首碼方式將失效。AcceptVerbsAttribute與HttpXXXAttribute都實現介面IActionHttpMethodProvider,所以最終的可以採用的Http要求方法是這兩種方式的並集。
Action方法名匹配
方法名的匹配因為比較簡單,在這裡我們來看一下VS2013預設產生的路由模板。
public static void Register(HttpConfiguration config) { // Web API 配置和服務 // Web API 路由 config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); }
VS2013預設情況下
提供的路由格式為"api/{controller}/{id}",並沒有提供action,所以在進行Action尋找的時候只會根據請求方式與參數進行匹配。
在Figure中定義兩個方法,分別是:
public IEnumerable<Figure> GetAll()
public Figure GetFigure(string firstName)
分別用以下url進行訪問:
http://localhost:7075/api/Figure
http://localhost:7075/api/Figure?firstName=Bran
此時他們調用的方法分別是GetAll, GetByQueryString
另外在FigureController再加一個無參無傳回值的Get方法,現在再用http://localhost:7075/api/Figure訪問就會得到"找到了與該請求匹配的多個操作"的錯誤訊息
參數匹配
在.NET中方法可以重載,所以在Action的選擇中也會有對參數的匹配過程。參數的來源於RouteData與QueryString。在匹配中,會出現以下幾種情況(為了在):
1.所有參數無預設值
這種情況下就會對所有參數進行匹配,如下:
public Figure GetFromQueryString(string firstName)
public Figure GetFromQueryString(string firstName,string lastName)
用以下Url進行訪問
http://localhost:7075/api/Figure/GetByQueryString?firstName=Bran
http://localhost:7075/api/Figure/GetByQueryString?firstName=Bran&lastName=Stack
分別調用的是GetFromQueryString(string firstName), GetFromQueryString(string firstName,string lastName。
但我們使用http://localhost:7075/api/Figure/GetByQueryString進行訪問,會返回"404 Not FOUND"。
2.存在預設只參數
首先可以確認的是,優先進行所有參數進行匹配,如果沒有匹配的Action再進行二輪匹配
public IEnumerable< Figure> GetFromQueryStringDefaultValue(string lastName="Stack")
public Figure GetFromQueryStringDefaultValue(string firstName, string lastName="Stack")
Action一通過以下url都可以訪問
http://localhost:7075/api/Figure/GetFromQueryStringDefaultValue
http://localhost:7075/api/Figure/GetFromQueryStringDefaultValue?lastName=Jon
Action二通過以下Action也都可以訪問
http://localhost:7075/api/Figure/GetFromQueryStringDefaultValue?firstName=Bran
http://localhost:7075/api/Figure/GetFromQueryStringDefaultValue?firstName=Bran&lastName=Stack
如果我們將Action二的firstName也設定預設值,那麼上面四個url進行訪問都和得到"找到了與該請求匹配的多個操作"的錯誤。
3.參數類型
方法的重載由參數數量、參數類型、參數類型順序決定,由於Web訪問的特殊性(只根據參數名匹配參數)所以參數類型順序不作為匹配的原則。上面的兩種情況都是對參數數量的匹配。在FigureController重載方法GetFromQueryStringType
public string GetFromQueryStringType(string x, string y)
public int GetFromQueryStringType(int x, int y)
通過http://localhost:7075/api/Figure/GetFromQueryStringType?x=1&y=2訪問。此時會得到"找到了與該請求匹配的多個操作"。
所以僅僅只通過參數類型(參數名相同)進行重載是不行的。
可以作為Action的方法
- 公用的執行個體方法
- 方法不是繼承自ApiController
源碼
Github: https://github.com/BarlowDu/WebAPI (API_2)
ASP.NET WebAPI 02-Action的選擇(一)