在谈如何在Get下使用复杂型别之前,先来看个东西,下面的程序代码是ApiController的范本程序代码
01.
public
class
ValuesController : ApiController
02.
{
03.
// GET api/<controller>
04.
public
IEnumerable<
string
> Get()
05.
{
06.
return
new
string
[] {
"value1"
,
"value2"
};
07.
}
08.
09.
// GET api/<controller>/5
10.
public
string
Get(
int
id)
11.
{
12.
return
"value"
;
13.
}
14.
15.
// POST api/<controller>
16.
public
void
Post([FromBody]
string
value)
17.
{
18.
}
19.
20.
// PUT api/<controller>/5
21.
public
void
Put(
int
id, [FromBody]
string
value)
22.
{
23.
}
24.
25.
// DELETE api/<controller>/5
26.
public
void
Delete(
int
id)
27.
{
28.
}
29.
}
可以注意到在Post & Put的方法参数有个关键词[FromBody],而Get & Delete则没有,事实上没有加[FromBody]则默认为[FromUri],[FromBody]表示由请求文件本体中取得数据,就像一般窗体Post Submit一样,取得数据的来源是由请求本体中取得,而[FromUri]则表示由URI中取得资料,就像在网址列中的所夹带的参数,除此之外预设对于复杂型别也是由[FromBody]取得资料。
有了以上初步的认知之后,我们来看一下,在ApiController的模板程序代码里,Get方法很单纯只有一个参数的传入且为简单的int型别,所以我们可以用Http : // … / api / Values / 1 这样的请求执行Get(int id)方法,但事实上并非每个设计都只有需要一个简单型别参数就能搞定,有时我们可能需要2个或以上的参数才能决定我们要取得的特定一笔数据,这时您可以这样做
路由设定改为接受二个参数,分别为{p1} & {p2}
1.
RouteTable.Routes.MapHttpRoute(
2.
name:
"DefaultApi"
,
3.
routeTemplate:
"webapi/{controller}/{p1}/{p2}"
,
4.
defaults:
new
{ id = System.Web.Http.RouteParameter.Optional }
5.
);
而ApiController里的Get方法则调整为
1.
public
string
Get(String p1, String p2)
2.
{
3.
return
p1 +
"/"
+ p2;
4.
}
执行结果如下
虽然这样可以解决我们需要有多个参数的需求,不过当参数一多的话,设计上就不是那么的方便,因此如果我们想要让Get方法可以接受一个复杂型别的参数时,如下程序代码,EmpQueryParameter是一个我们自订的型别,具有二个属性,而Get方法的参数改为接受这个自订型别 www.it165.net
01.
public
class
EmpQueryParameter
02.
{
03.
public
String FirstName {
get
;
set
; }
04.
public
String LastName {
get
;
set
; }
05.
}
06.
07.
08.
09.
public
string
Get(EmpQueryParameter parameter)
10.
{
11.
return
parameter.FirstName +
"/"
+ parameter.LastName;
12.
}
接着我们把路由的设定改为如下的设定
01.
void
Application_Start(
object
sender, EventArgs e)
02.
{
03.
// 应用程序启动时执行的程序代码
04.
BundleConfig.RegisterBundles(BundleTable.Bundles);
05.
AuthConfig.RegisterOpenAuth();
06.
07.
RouteTable.Routes.MapHttpRoute(
08.
name:
"DefaultApi"
,
09.
routeTemplate:
"webapi/{controller}"
,
10.
defaults:
new
{ id = System.Web.Http.RouteParameter.Optional }
11.
);
12.
}
然后直接执行,由于我们的参数是一个复杂型别,因此我们试着在网址列输入Http : // … / webapi / values ?firstname=ian&lastname=chen 的请求,结果你会发现出现错误 "并未将对象参考设定为对象的执行个体。"
为什么会引发这个错误呢?在本文一开始笔者即提到了预设对于复杂型别是由[FromBody]取得数据,所以我们的请求虽然在网址列夹带了上?firstname=ian&lastname=chen 了,但它并不会被取得,因此就会出现这个例外错误,此时我们只要把Get方法稍加修饰一下,在参数前面指定[FromUri] 关键词
1.
public
string
Get([FromUri] EmpQueryParameter parameter)
2.
{
3.
return
parameter.FirstName +
"/"
+ parameter.LastName;
4.
}
接着再执行一次,就可以看到顺利取得参数值
在多参数需求下,使用复杂型别的好处在于,我们可以不需要因受限在路由的设定,而必须要很清楚的记得参数位置顺序,并且也不用因为不特定的参数数量而导致路由规划复杂化,如同上面的范例,即使我们把请求参数改为?lastname=chen&firstname=ian,顺序相反时,对于结果也不会产生异常,在Mapping上是以参数名称对应型别的属性名称,此外即使我们传了一个不存在型别里的属性名称参数值,也不会引发错误,该参数只会被忽略掉。因此在设计上会更佳方便及具有弹性。
若本文对您有所帮助,欢迎转贴,但请在加注【转贴】及来源出处,并在附上本篇的超级链接,感恩您的配合啰。