WebApi接口传参不再困惑:传参详解

来源:互联网 发布:mac如何装虚拟机系统 编辑:程序博客网 时间:2024/06/08 07:35

目录(?)[-]

  1. 一get请求
    1. 基础类型参数
    2. 实体作为参数
    3. 数组作为参数
    4. 怪异的get请求
      1. 1WebApi的方法名称以get开头
      2. 2WebApi的方法名称不以get开头
  2. 二post请求
    1. 基础类型参数
      1. 1错误的写法
      2. 1错误写法
      3. 2正确用法
      4. 3推荐用法
  3. 三put请求
    1. 基础类型参数
    2. 实体作为参数
    3. 数组作为参数
  4. 四delete请求
  5. 五总结


一、get请求

对于取数据,我们使用最多的应该就是get请求了吧。下面通过几个示例看看我们的get请求参数传递。

1、基础类型参数

[csharp] view plain copy
  1. [HttpGet]  
  2. public string GetAllChargingData(int id, string name)  
  3. {  
  4.     return "ChargingData" + id;  
  5. }  
[javascript] view plain copy
  1. $.ajax({  
  2.         type: "get",  
  3.         url: "http://localhost:27221/api/Charging/GetAllChargingData",  
  4.         data: { id: 1, name: "Jim", bir: "1988-09-11"},  
  5.         success: function (data, status) {  
  6.             if (status == "success") {  
  7.                 $("#div_test").html(data);  
  8.             }  
  9.         }  
  10.     });  
 这是get请求最基础的参数传递方式,没什么特别好说的。

2、实体作为参数

如果我们在get请求时想将实体对象做参数直接传递到后台,是否可行呢?我们来看看。

[csharp] view plain copy
  1. public class TB_CHARGING  
  2.     {  
  3.         /// <summary>  
  4.         /// 主键Id  
  5.         /// </summary>  
  6.         public string ID { getset; }  
  7.   
  8.         /// <summary>  
  9.         /// 充电设备名称  
  10.         /// </summary>  
  11.         public string NAME { getset; }  
  12.   
  13.         /// <summary>  
  14.         /// 充电设备描述  
  15.         /// </summary>  
  16.         public string DES { getset; }  
  17.   
  18.         /// <summary>  
  19.         /// 创建时间  
  20.         /// </summary>  
  21.         public DateTime CREATETIME { getset; }  
  22.     }  
[csharp] view plain copy
  1. [HttpGet]  
  2. public string GetByModel(TB_CHARGING oData)  
  3. {  
  4.      return "ChargingData" + oData.ID;  
  5. }  
[javascript] view plain copy
  1. $.ajax({  
  2.         type: "get",  
  3.         url: "http://localhost:27221/api/Charging/GetByModel",  
  4.         contentType: "application/json",  
  5.         data: { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },  
  6.         success: function (data, status) {  
  7.             if (status == "success") {  
  8.                 $("#div_test").html(data);  
  9.             }  
  10.         }  
  11.     });  

测试结果: 在get请求时,我们直接将json对象当做实体传递后台,后台是接收不到的。这是为什么呢?我们来看看对应的http请求


[html] view plain copy
  1. <img src="http://images2015.cnblogs.com/blog/459756/201603/459756-20160331104121410-719598113.png" alt="" />  

原来,get请求的时候,默认是将参数全部放到了url里面直接以string的形式传递的,后台自然接不到了。

原因分析:还记得有面试题问过get和post请求的区别吗?其中有一个区别就是get请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),而post请求则是放在http协议包的包体中。

根据园友们的提议,Get请求的时候可以在参数里面加上[FromUri]即可直接得到对象。还是贴上代码:

[javascript] view plain copy
  1. var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" };  
  2.     $.ajax({  
  3.         type: "get",  
  4.         url: "http://localhost:27221/api/Charging/GetAllChargingData",  
  5.         data: postdata,  
  6.         success: function (data, status) { }  
  7.     });  
[csharp] view plain copy
  1. [HttpGet]  
  2.         public string GetAllChargingData([FromUri]TB_CHARGING obj)  
  3.         {  
  4.             return "ChargingData" + obj.ID;  
  5.         }  

得到结果:

如果你不想使用[FromUri]这些在参数里面加特性的这种“怪异”写法,也可以采用先序列化,再在后台反序列的方式。

[javascript] view plain copy
  1. $.ajax({  
  2.         type: "get",  
  3.         url: "http://localhost:27221/api/Charging/GetByModel",  
  4.         contentType: "application/json",  
  5.         data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },  
  6.         success: function (data, status) {  
  7.             if (status == "success") {  
  8.                 $("#div_test").html(data);  
  9.             }  
  10.         }  
  11.     });  
[csharp] view plain copy
  1. [HttpGet]  
  2.         public string GetByModel(string strQuery)  
  3.         {  
  4.             TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);  
  5.             return "ChargingData" + oData.ID;  
  6.         }  

这样在后台得到我们序列化过的对象,再通过反序列化就能得到对象。

在url里面我们可以看到它自动给对象加了一个编码:

3、数组作为参数

一般get请求不建议将数组作为参数,因为我们知道get请求传递参数的大小是有限制的,最大1024字节,数组里面内容较多时,将其作为参数传递可能会发生参数超限丢失的情况。

4、“怪异”的get请求

为什么会说get请求“怪异”呢?我们先来看看下面的两种写法对比。

(1)WebApi的方法名称以get开头

[javascript] view plain copy
  1. $.ajax({  
  2.         type: "get",  
  3.         url: "http://localhost:27221/api/Charging/GetByModel",  
  4.         contentType: "application/json",  
  5.         data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },  
  6.         success: function (data, status) {  
  7.             if (status == "success") {  
  8.                 $("#div_test").html(data);  
  9.             }  
  10.         }  
  11.     });  

[csharp] view plain copy
  1. [HttpGet]  
  2.         public string GetByModel(string strQuery)  
  3.         {  
  4.             TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);  
  5.             return "ChargingData" + oData.ID;  
  6.         }  

这是标准写法,后台加[HttpGet],参数正常得到:

为了对比,我将[HttpGet]去掉,然后再调用

[csharp] view plain copy
  1. //[HttpGet]  
  2.       public string GetByModel(string strQuery)  
  3.       {  
  4.           TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);  
  5.           return "ChargingData" + oData.ID;  
  6.       }  

貌似没有任何问题!有人就想,那是否所有的get请求都可以省略掉[HttpGet]这个标注呢。我们试试便知。

(2)WebApi的方法名称不以get开头

我们把之前的方法名由GetByModel改成FindByModel,这个再正常不过了,很多人查询就不想用Get开头,还有直接用Query开头的。这个有什么关系吗?有没有关系,我们以事实说话。


[javascript] view plain copy
  1. $.ajax({  
  2.         type: "get",  
  3.         url: "http://localhost:27221/api/Charging/FindByModel",  
  4.         contentType: "application/json",  
  5.         data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },  
  6.         success: function (data, status) {  
  7.             if (status == "success") {  
  8.                 $("#div_test").html(data);  
  9.             }  
  10.         }  
  11.     });  

[csharp] view plain copy
  1. [HttpGet]  
  2.         public string FindByModel(string strQuery)  
  3.         {  
  4.             TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);  
  5.             return "ChargingData" + oData.ID;  
  6.         }  


貌似又可行,没有任何问题啊。根据上面的推论,我们去掉[HttpGet]也是可行的,好,我们注释掉[HttpGet],运行起来试试。


结果是不进断点,有些人不信,我们在浏览器里面看看http请求:


呵呵,这就奇怪了,就改了个方法名,至于这样么?还真至于!

博主的理解是:方法名以Get开头,WebApi会自动默认这个请求就是get请求,而如果你以其他名称开头而又不标注方法的请求方式,那么这个时候服务器虽然找到了这个方法,但是由于请求方式不确定,所以直接返回给你405——方法不被允许的错误。

最后结论:所有的WebApi方法最好是加上请求的方式([HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]),不要偷懒,这样既能防止类似的错误,也有利于方法的维护,别人一看就知道这个方法是什么请求。

这也就是为什么很多人在园子里面问道为什么方法名不加[HttpGet]就调用不到的原因!


二、post请求

在WebApi的RESETful风格里面,API服务的增删改查,分别对应着http的post/delete/put/get请求。我们下面就来说说post请求参数的传递方式。

1、基础类型参数

 post请求的基础类型的参数和get请求有点不一样,我们知道get请求的参数是通过url来传递的,而post请求则是通过http的请求体中传过来的,WebApi的post请求也需要从http的请求体里面去取参数。

(1)错误的写法

[javascript] view plain copy
  1. $.ajax({  
  2.         type: "post",  
  3.         url: "http://localhost:27221/api/Charging/SaveData",  
  4.         data: { NAME: "Jim" },  
  5.         success: function (data, status) {  
  6.             if (status == "success") {  
  7.                 $("#div_test").html(data);  
  8.             }  
  9.         }  
  10.     });  

[csharp] view plain copy
  1. [HttpPost]  
  2.         public bool SaveData(string NAME)  
  3.         {  
  4.             return true;  
  5.         }  

这是一种看上去非常正确的写法,可是实际情况是:


(2)正确的用法

[javascript] view plain copy
  1. $.ajax({  
  2.        type: "post",  
  3.        url: "http://localhost:27221/api/Charging/SaveData",  
  4.        data: { """Jim" },  
  5.        success: function (data, status) {}  
  6.    });  

[csharp] view plain copy
  1. [HttpPost]  
  2. public bool SaveData([FromBody]string NAME)  
  3. {  
  4.     return true;  
  5. }  

这是一种另许多人头痛的写法,但是没办法,这样确实能得到我们的结果:


我们一般的通过url取参数的机制是键值对,即某一个key等于某一个value,而这里的FromBody和我们一般通过url取参数的机制则不同,它的机制是=value,没有key的概念,并且如果你写了key(比如你的ajax参数写的{NAME:"Jim"}),后台反而得到的NAME等于null。不信你可以试试。

上面讲的都是传递一个基础类型参数的情况,那么如果我们需要传递多个基础类型呢?按照上面的推论,是否可以([FromBody]string NAME, [FromBody]string DES)这样写呢。试试便知。

(1)错误写法

[javascript] view plain copy
  1. $.ajax({  
  2.         type: "post",  
  3.         url: "http://localhost:27221/api/Charging/SaveData",  
  4.         data: { """Jim","":"备注" },  
  5.         success: function (data, status) {}  
  6.     });  

[csharp] view plain copy
  1. [HttpPost]  
  2.         public bool SaveData([FromBody]string NAME, [FromBody] string DES)  
  3.         {  
  4.             return true;  
  5.         }  

得到结果


这说明我们没办法通过多个[FromBody]里面取值,此法失败。

(2)正确用法

既然上面的办法行不通,那我们如何传递多个基础类型的数据呢?很多的解决办法是新建一个类去包含传递的参数,博主觉得这样不够灵活,因为如果我们前后台每次传递多个参数的post请求都去新建一个类的话,我们系统到时候会有多少个这种参数类?维护起来那是相当的麻烦的一件事!所以博主觉得使用dynamic是一个很不错的选择。我们来试试。

[javascript] view plain copy
  1. $.ajax({  
  2.         type: "post",  
  3.         url: "http://localhost:27221/api/Charging/SaveData",  
  4.         contentType: 'application/json',  
  5.         data: JSON.stringify({ NAME: "Jim",DES:"备注" }),  
  6.         success: function (data, status) {}  
  7.     });  

[csharp] view plain copy
  1. [HttpPost]  
  2.         public object SaveData(dynamic obj)  
  3.         {  
  4.             var strName = Convert.ToString(obj.NAME);  
  5.             return strName;  
  6.         }  

通过dynamic动态类型能顺利得到多个参数,省掉了[FromBody]这个累赘,并且ajax参数的传递不用使用"无厘头"的{"":"value"}这种写法,有没有一种小清新的感觉~~有一点需要注意的是这里在ajax的请求里面需要加上参数类型为Json,即 contentType: 'application/json', 这个属性。

(3)推荐用法

通过上文post请求基础类型参数的传递,我们了解到了dynamic的方便之处,为了避免[FromBody]这个累赘和{"":"value"}这种"无厘头"的写法。博主推荐所有基础类型使用dynamic来传递,方便解决了基础类型一个或多个参数的传递,示例如上文。如果园友们有更好的办法,欢迎讨论。


三、put请求

WebApi里面put请求一般用于对象的更新。它和用法和post请求基本相同。同样支持[FromBody],同样可以使用dynamic。

1、基础类型参数

[javascript] view plain copy
  1. $.ajax({  
  2.         type: "put",  
  3.         url: "http://localhost:27221/api/Charging/Update",  
  4.         contentType: 'application/json',  
  5.         data: JSON.stringify({ ID: "1" }),  
  6.         success: function (data, status) {}  
  7.     });  

[csharp] view plain copy
  1. [HttpPut]  
  2.         public bool Update(dynamic obj )  
  3.         {  
  4.             return true;  
  5.         }  


2、实体作为参数

和post请求相同。

3、数组作为参数

和post请求相同。

四、delete请求

顾名思义,delete请求肯定是用于删除操作的。参数传递机制和post也是基本相同。下面简单给出一个例子,其他情况参考post请求。

[javascript] view plain copy
  1. var arr = [  
  2.         { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },  
  3.         { ID: "2", NAME: "Lilei", CREATETIME: "1990-12-11" },  
  4.         { ID: "3", NAME: "Lucy", CREATETIME: "1986-01-10" }  
  5.     ];  
  6.     $.ajax({  
  7.         type: "delete",  
  8.         url: "http://localhost:27221/api/Charging/OptDelete",  
  9.         contentType: 'application/json',  
  10.         data: JSON.stringify(arr),  
  11.         success: function (data, status) {}  
  12.     });  


 

[csharp] view plain copy
  1. [HttpDelete]  
  2.         public bool OptDelete(List<TB_CHARGING> lstChargin)  
  3.         {  
  4.             return true;  
  5.         }  

五、总结

以上比较详细的总结了WebApi各种请求的各种参数传递。每种情况都是博主实际代码测试过的,内容不难,但如果刚接触这么些东西还是需要一点时间去熟悉的,在此做个总结,希望能帮到刚刚接触WebApi的园友们。如果本文能帮到你,不妨推荐下,您的推荐是博主继续总结的动力!

原创粉丝点击