在前面的幾篇文章中我們都是采用在URI中元數據類型進行傳參,實際上ASP.NET Web API也提供了對URI進行復雜參數的綁定方式--Model綁定。這里的Model可以簡單的理解為目標Anction方法的某個參數。
eg:
public Figure GetFigureFromQueryString([ModelBinder]Figure figure)
{
return figure;
}
請求url: http://localhost:4044/api/Figure/GetFigureFromQueryString?FirstName=Bran&LastName=Stack
結果:
{
"FirstName": "Bran",
"LastName": "Stack"
}
(本篇為了更好的體現綁定結果,所有Anction的返回結果都是請求參數或整合的后的請求參數)
ModelBinder
在之前的文章中多次提到URI的數據主要來源於兩種方式:Route,QueryString。但是URI只提供簡單的基礎數據類型,在上面的例中,我們會發現參數變成了類。ModelBinderAttribute提供了基礎數據類型向復雜類型數據轉換的功能。
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Parameter, Inherited = true, AllowMultiple = false)]
public class ModelBinderAttribute : ParameterBindingAttribute
{
}
從定義中我們可以看出ModelBinder的AttributeUsage可以看出來ModelBinder可以用於類型與參數。下面我就列舉一些Model綁定的形式。
-
簡單類
這里所說的簡單類是指數據是指類的公開屬性是基礎數據類型。比如我們之前一直使用的Figure類。
public class Figure
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
還是以本文開始的GetFigureFromQueryString([ModelBinder]Figure figure) 為例。因為該Action中只采用了一個參數。所以在傳參的過程中只需要將FirstName,LastName作為QueryString傳遞,ModelBinder將轉換出Figure對象。
http://localhost:4044/api/Figure/GetFigureFromQueryString?FirstName=Bran&LastName=Stack
同時我們也可以采用route形式進行傳參:
[Route("GetFigureFromRoute/{FirstName}/{LastName}")]
public Figure GetFigureFromRoute(Figure figure)
url:
http://localhost:4044/api/Figure/GetFigureFromRoute/Bran/Stack
當然以此類推也也可以進行混合的傳參:
還是基於 GetFigureFromRoute Action
我們用以下url進行訪問:
http://localhost:4044/api/Figure/GetFigureFromRoute/Bran/Stack?FirstName=Robb
那我們得到的結果將是:
{
"FirstName": "Robb",
"LastName": "Stack"
}
由此可以看出
QueryString參數的優先級是高於Route參數的
2.多參數(簡單類)
第一種情況我們是考慮了一個參數,現在我們把參數變成兩個,如下:
List<Figure> 方法名 (Figure a, Figure b)
因為這個時候出現了兩個類型相同的參數,僅靠屬性名已經不能對參數進行區別。這個時候WebAPI為我們提供了前綴形式對參數進行區分。下面就以Route的方式做一demo:、
[Route("GetTwoFigureFromRoute/{a.FirstName}/{a.LastName}/{b.FirstName}/{b.LastName}")]
public List<Figure> GetTwoFigureFromRoute(Figure a, Figure b)
我們對路由進行一個簡單分析:即{參數名}.{屬性名} 作為路由的key
{a.FirstName}:參數a的FirstName屬性
{a.LastName}:參數a的LastName屬性
{b.FirstName}:參數b的FirstName屬性
{b.LastName}:參數b的LastName屬性
用以下url訪問
http://localhost:4044/api/Figure/GetTwoFigureFromRoute/Bran/Stack/Robb/Stack
得到的結果就是:
[
{
"FirstName": "Bran",
"LastName": "Stack"
},
{
"FirstName": "Robb",
"LastName": "Stack"
}
]
對於QueryString形式傳參也非常簡單,直接將{參數名}.{屬性名} 作為QueryString的key.比如:
public List<Figure> GetTwoFigureFromQueryString(Figure a, Figure b)
url:
http://localhost:4044/api/Figure/GetTwoFigureFromQueryString?a.FirstName=Bran&a.LastName=Stack&b.FirstName=Robb&b.LastName=Stack
將得到如Route形式一樣的結果
3.復雜類
現在我們對Figure添加一個Direwolf類的屬性Direwolf,讓其變為一個復雜類
public class Figure
{
public Direwolf Direwolf { get; set; }
}
public class Direwolf
{
public string Name { get; set; }
public string Color { get; set; }
}
在傳參數的過程中顯然我們不能對直接對Direwolf屬性賦值,所以我們要對Direwolf屬性進行拆分,這個時候我也要用到前綴的方式進行傳參。如下:
public Figure GetComplexFigureFromQueryString(Figure figure)
url:
http://localhost:4044/api/Figure/GetComplexFigureFromQueryString?FirstName=Jon&LastName=Snow&Direwolf.Color=White&Direwolf.Name=Summer
結果:
{
"FirstName": "Bran",
"LastName": "Stack",
"Direwolf": {
"Name": "Summer",
"Color": "White"
}
}
對於Route形式也是一樣:
[Route("GetComplexFigureFromRoute/{FirstName}/{LastName}/{Direwolf.Name}/{Direwolf.Color}")]
public Figure GetComplexFigureFromRoute(Figure figure)
url:
http://localhost:4044/api/Figure/GetComplexFigureFromRoute/Bran/Stack/Grey/Summer
對於多參數的形式也照樣可以處理:
public List<Figure> GetTwoComplexFigureFromQueryString(Figure a, Figure b)
url:
http://localhost:4044/api/Figure/GetTwoComplexFigureFromQueryString?a.FirstName=Bran&a.LastName=Stack&a.Direwolf.Color=Grey&a.Direwolf.Name=Summer&b.FirstName=Jon&b.LastName=Snow&b.Direwolf.Color=White&b.Direwolf.Name=Ghost
4.集合類型
集合類型因為存在長度的確定性,所以還是需要通過前綴的方式去指定序列號,如下:
public List<int> GetList([ModelBinder] List<int> list)
{
return list;
}
url:
http://localhost:4044/api/Figure/GetList?[0]=0&[1]=1&[2]=2&[3]=3
結果:
[
0,
1,
2,
3
]
注意
序列號必須是從0開始連續的整數,不然就只能得到序列號斷裂之前的數據,如:
url:
http://localhost:4044/api/Figure/GetList?[0]=0&[2]=1&[2]=2&[3]=3
結果:
[
0
]
另外,如果要采用Route形式的傳參方式,就必須考慮數據的長度問題。
5字典類型
WebAPI在數據字典類型的先將數據轉化成KeyValuePair的集合類型,再轉化成字典類型。所以再傳參的時候我們可以采用與集合類型一致的方式。如:
public Dictionary<string, int> GetDictionary([ModelBinder]Dictionary<string, int> dic)
url:
http://localhost:4044/api/Figure/GetDictionary?[0].Key=a&[0].Value=1&[1].Key=b&[1].Value=2
結果
{
"a": 1,
"b": 2
}
源碼
Github: https://github.com/BarlowDu/WebAPI (API_4)