本文将分享从BaseHTTPHandler解析httpGET和POST参数?的详细内容,并且还将对http详解进行详尽解释,此外,我们还将为大家带来关于.net-4.0–从自定义IHttpHandle
本文将分享从BaseHTTPHandler解析http GET和POST参数?的详细内容,并且还将对http详解进行详尽解释,此外,我们还将为大家带来关于.net-4.0 – 从自定义IHttpHandler调用MvcHttpHandler.ExecuteRequest时出错、ajax 参数传递之 [HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete] 请求、ajax参数传递之[HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]请求、AndroidAsyncHttp 临时修复 JsonHttpResponseHandler 避免死循环的相关知识,希望对你有所帮助。
本文目录一览:- 从BaseHTTPHandler解析http GET和POST参数?(http详解)
- .net-4.0 – 从自定义IHttpHandler调用MvcHttpHandler.ExecuteRequest时出错
- ajax 参数传递之 [HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete] 请求
- ajax参数传递之[HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]请求
- AndroidAsyncHttp 临时修复 JsonHttpResponseHandler 避免死循环
从BaseHTTPHandler解析http GET和POST参数?(http详解)
BaseHTTPServer模块中的BaseHTTPHandler似乎没有提供任何方便的方法来访问http请求参数。从路径解析GET参数和从请求正文解析POST参数的最佳方法是什么?
现在,我正在将它用于GET:
def do_GET(self): parsed_path = urlparse.urlparse(self.path) try: params = dict([p.split(''='') for p in parsed_path[4].split(''&'')]) except: params = {}
这适用于大多数情况,但是我想要更强大的功能,可以正确处理编码和类似空参数的情况。理想情况下,我想要的是小型独立的产品,而不是完整的Web框架。
答案1
小编典典您可以尝试使用Werkzeug模块,基本的Werkzeug库不是太大,如果需要,您只需提取这段代码即可完成。
该url_decode
方法返回一个MultiDict并具有编码支持:)
与该urlparse.parse_qs
方法相反,Werkzeug版本负责:
- 编码方式
- 多个值
- 排序
如果不需要这些(或者在编码的情况下,请使用Python 3),则可以随意使用内置解决方案。
.net-4.0 – 从自定义IHttpHandler调用MvcHttpHandler.ExecuteRequest时出错
它在asp.net MVC2中运行良好,但在我使用IISExpress 7.5将代码迁移到MVC4之后,我开始在行上获得InvalidOperationException:
httpHandler.ProcessRequest(HttpContext.Current);
有消息:
‘HttpContext.SetSessionStateBehavior’ can only be invoked before
‘HttpApplication.AcquireRequestState’ event is raised.
ASP.NET Development Server不会出现任何问题.
有谁知道这里发生了什么,以及如何解决它?
解决方法
看到这个问题:MVC3 Application Inside Webforms Application Routing is throwing a HttpContext.SetSessionStateBehavior Error in IIS7.5
ajax 参数传递之 [HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete] 请求

$.ajax({
type: "get",
url: "http://localhost:27221/api/Charging/GetByModel",
contentType: "application/json",
data: { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
success: function (data, status) {
if (status == "success") {
$("#div_test").html(data);
}
}
});

[HttpGet]
public string GetAllChargingData([FromUri]TB_CHARGING obj)
{
return "ChargingData" + obj.ID;
}
得到结果:
如果你不想使用 [FromUri] 这些在参数里面加特性的这种 “怪异” 写法,也可以采用先序列化,再在后台反序列的方式。

$.ajax({
type: "get",
url: "http://localhost:27221/api/Charging/GetByModel",
contentType: "application/json",
data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },
success: function (data, status) {
if (status == "success") {
$("#div_test").html(data);
}
}
});

[HttpGet]
public string GetByModel(string strQuery)
{
TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);
return "ChargingData" + oData.ID;
}
这样在后台得到我们序列化过的对象,再通过反序列化就能得到对象。
数组作为参数
一般 get 请求不建议将数组作为参数,因为我们知道 get 请求传递参数的大小是有限制的,最大 1024 字节,数组里面内容较多时,将其作为参数传递可能会发生参数超限丢失的情况。

$.ajax({
type: "get",
url: "http://localhost:27221/api/Charging/FindByModel",
contentType: "application/json",
data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) },
success: function (data, status) {
if (status == "success") {
$("#div_test").html(data);
}
}
});

[HttpGet]
public string FindByModel(string strQuery)
{
TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery);
return "ChargingData" + oData.ID;
}
方法名以 Get 开头,WebApi 会自动默认这个请求就是 get 请求,而如果你以其他名称开头而又不标注方法的请求方式,那么这个时候服务器虽然找到了这个方法,但是由于请求方式不确定,所以直接返回给你 405—— 方法不被允许的错误。
最后结论:所有的 WebApi 方法最好是加上请求的方式([HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]),不要偷懒,这样既能防止类似的错误,也有利于方法的维护,别人一看就知道这个方法是什么请求。
二、post 请求
在 WebApi 的 RESETful 风格里面,API 服务的增删改查,分别对应着 http 的 post/delete/put/get 请求。我们下面就来说说 post 请求参数的传递方式。
1、基础类型参数
post 请求的基础类型的参数和 get 请求有点不一样,我们知道 get 请求的参数是通过 url 来传递的,而 post 请求则是通过 http 的请求体中传过来的,WebApi 的 post 请求也需要从 http 的请求体里面去取参数。
(1)错误的写法

$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
data: { NAME: "Jim" },
success: function (data, status) {
if (status == "success") {
$("#div_test").html(data);
}
}
});
[HttpPost]
public bool SaveData(string NAME)
{
return true;
}

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

$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
data: { "": "Jim" },
success: function (data, status) {}
});
[HttpPost]
public bool SaveData([FromBody]string NAME)
{
return true;
}

这是一种另许多人头痛的写法,但是没办法,这样确实能得到我们的结果:
我们一般的通过 url 取参数的机制是键值对,即某一个 key 等于某一个 value,而这里的 FromBody 和我们一般通过 url 取参数的机制则不同,它的机制是 = value,没有 key 的概念,并且如果你写了 key (比如你的 ajax 参数写的 {NAME:"Jim"}),后台反而得到的 NAME 等于 null。不信你可以试试。
上面讲的都是传递一个基础类型参数的情况,那么如果我们需要传递多个基础类型呢?按照上面的推论,是否可以 ([FromBody] string NAME, [FromBody] string DES) 这样写呢。试试便知。
(1)错误写法

$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
data: { "": "Jim","":"备注" },
success: function (data, status) {}
});
[HttpPost]
public bool SaveData([FromBody]string NAME, [FromBody] string DES)
{
return true;
}

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

$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
contentType: ''application/json'',
data: JSON.stringify({ NAME: "Jim",DES:"备注" }),
success: function (data, status) {}
});
[HttpPost]
public object SaveData(dynamic obj)
{
var strName = Convert.ToString(obj.NAME);
return strName;
}

通过 dynamic 动态类型能顺利得到多个参数,省掉了 [FromBody] 这个累赘,并且 ajax 参数的传递不用使用 "无厘头" 的 {"":"value"} 这种写法,有没有一种小清新的感觉~~有一点需要注意的是这里在 ajax 的请求里面需要加上参数类型为 Json,即 contentType: ''application/json'', 这个属性。
通过上文 post 请求基础类型参数的传递,我们了解到了 dynamic 的方便之处,为了避免 [FromBody] 这个累赘和 {"":"value"} 这种" 无厘头 " 的写法。博主推荐所有基础类型使用 dynamic 来传递,方便解决了基础类型一个或多个参数的传递,示例如上文
2、实体作为参数
(1)单个实体作为参数
上面我们通过 dynamic 类型解决了 post 请求基础类型数据的传递问题,那么当我们需要传递一个实体作为参数该怎么解决呢?我们来看下面的代码便知:

$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
data: { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
success: function (data, status) {}
});
[HttpPost]
public bool SaveData(TB_CHARGING oData)
{
return true;
}

得到结果
原理解释:使用实体作为参数的时候,前端直接传递普通 json,后台直接使用对应的类型去接收即可,不用 FromBody。但是这里需要注意的一点就是,这里不能指定 contentType 为 appplication/json,否则,参数无法传递到后台。我们来看看它默认的 contentType 是什么:
为了弄清楚原因,博主查了下 http 的 Content-Type 的类型。看到如下说明:
- application/x-www-form-urlencoded : <form encType=””> 中默认的 encType,form 表单数据被编码为 key/value 格式发送到服务器(表单默认的提交数据的格式);
- application/json : JSON 数据格式
也就是说 post 请求默认是将表单里面的数据的 key/value 形式发送到服务,而我们的服务器只需要有对应的 key/value 属性值的对象就可以接收到。而如果使用 application/json,则表示将前端的数据以序列化过的 json 传递到后端,后端要把它变成实体对象,还需要一个反序列化的过程。按照这个逻辑,那我们如果指定 contentType 为 application/json,然后传递序列化过的对象应该也是可以的啊。博主好奇心重,还是打算一试到底,于是就有了下面的代码:

var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" };
$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
contentType: ''application/json'',
data: JSON.stringify(postdata),
success: function (data, status) {}
});
[HttpPost]
public bool SaveData(TB_CHARGING lstCharging)
{
return true;
}

得到结果:
尝试成功,也就是说,两种写法都是可行的。如果你指定了 contentType 为 application/json,则必须要传递序列化过的对象;如果使用 post 请求的默认参数类型,则前端直接传递 json 类型的对象即可。
(2)实体和基础类型一起作为参数传递
有些时候,我们需要将基础类型和实体一起传递到后台,这个时候,我们神奇的 dynamic 又派上用场了。

var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" };
$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
contentType: ''application/json'',
data: JSON.stringify({ NAME:"Lilei", Charging:postdata }),
success: function (data, status) {}
});
[HttpPost]
public object SaveData(dynamic obj)
{
var strName = Convert.ToString(obj.NAME);
var oCharging = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(Convert.ToString(obj.Charging));
return strName;
}

得到结果:
3、数组作为参数
(1)基础类型数组

var arr = ["1", "2", "3", "4"];
$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
contentType: ''application/json'',
data: JSON.stringify(arr),
success: function (data, status) { }
});
[HttpPost]
public bool SaveData(string[] ids)
{
return true;
}

得到结果:
(2)实体集合

var arr = [
{ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
{ ID: "2", NAME: "Lilei", CREATETIME: "1990-12-11" },
{ ID: "3", NAME: "Lucy", CREATETIME: "1986-01-10" }
];
$.ajax({
type: "post",
url: "http://localhost:27221/api/Charging/SaveData",
contentType: ''application/json'',
data: JSON.stringify(arr),
success: function (data, status) {}
});
[HttpPost]
public bool SaveData(List<TB_CHARGING> lstCharging)
{
return true;
}

得到结果:
4、后台发送请求参数的传递
上面写了那么多,都是通过前端的 ajax 请求去做的,我们知道,如果调用方不是 web 项目,比如 Android 客户端,可能需要从后台发送 http 请求来调用我们的接口方法,如果我们通过后台去发送请求是否也是可行的呢?我们以实体对象作为参数来传递写写代码试一把。

public void TestReques()
{
//请求路径
string url = "http://localhost:27221/api/Charging/SaveData";
//定义request并设置request的路径
WebRequest request = WebRequest.Create(url);
request.Method = "post";
//初始化request参数
string postData = "{ ID: \"1\", NAME: \"Jim\", CREATETIME: \"1988-09-11\" }";
//设置参数的编码格式,解决中文乱码
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
//设置request的MIME类型及内容长度
request.ContentType = "application/json";
request.ContentLength = byteArray.Length;
//打开request字符流
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
//定义response为前面的request响应
WebResponse response = request.GetResponse();
//获取相应的状态代码
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
//定义response字符流
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();//读取所有
Console.WriteLine(responseFromServer);
}

当代码运行到 request.GetResponse () 这一句的时候,API 里面进入断点
尝试成功。
三、put 请求
WebApi 里面 put 请求一般用于对象的更新。它和用法和 post 请求基本相同。同样支持 [FromBody],同样可以使用 dynamic。
1、基础类型参数

$.ajax({
type: "put",
url: "http://localhost:27221/api/Charging/Update",
contentType: ''application/json'',
data: JSON.stringify({ ID: "1" }),
success: function (data, status) {}
});
[HttpPut]
public bool Update(dynamic obj )
{
return true;
}

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

var arr = [
{ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" },
{ ID: "2", NAME: "Lilei", CREATETIME: "1990-12-11" },
{ ID: "3", NAME: "Lucy", CREATETIME: "1986-01-10" }
];
$.ajax({
type: "delete",
url: "http://localhost:27221/api/Charging/OptDelete",
contentType: ''application/json'',
data: JSON.stringify(arr),
success: function (data, status) {}
});
[HttpDelete]
public bool OptDelete(List<TB_CHARGING> lstChargin)
{
return true;
}

博文的一点评论:
dynamic 虽然很巧妙地解决了从请求 body 中获取参数。但是这样不利于生成 api 文档。
ps:一般都是用 pagehelp 等工具,自动读取元数据,生成 api 文档的。
如果用 dynamic 的话,生成的文档就只有一个 dynamic 类型的参数,这样 api 调用者就无法明确 api 的参数了。
还有接收参数定义为 dynamic 类型的话,后续维护或升级太麻烦。
如果是 post 操作。文中介绍了两种传递实体参数的方法
第一种:
1
|
data: { ID:
"1"
, NAME:
"Jim"
, CREATETIME:
"1988-09-11"
}
|
不需要指定 contentType。
第二种:
1
|
data:
"{\"SoldToParty\":\"fdsfds\",\"SaleOrg\":\"fdsfds\",\"Channel\":\"ffffff\",\"Division\":\"dfdfsdsfd\"}"
|
需要指定 contentType:"application/json"。两种方式后台都可以得到实体。不知道你的 Json 字符串是怎么得到的,是拼的字符串?建议使用 JSON.stringify ({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11"}) 这种方式得到 json 字符串。
HttpPost 传单个变量
[HttpPost]
public JsonResult DeleteFrequencyInfo(List<string> ids)
$.ajax(
{
url: "/Frequency/DeleteFrequencyInfo",
type: "post",
data: { "ids": deleted },
dataType: "json",
HttpPost 传实体
[HttpPost]
public JsonResult GetFrequencyPrint(FrequencyPrintQO request)
public class FrequencyPrintQO
{
public string FrequencyId { get; set; }
public List<string> Freedombarcodes { get; set; }
}
$.ajax({
type: "POST",
url: ''/Print/GetFrequencyPrint'',
dataType: "Json",
async: false, // 此处必须定义为同步
data: {Freedombarcodes: freedombarcodes},
ajax参数传递之[HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]请求
$.ajax({ type: "get", url: "http://localhost:27221/api/Charging/GetByModel", contentType: "application/json", data: { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } } });
[HttpGet] public string GetAllChargingData([FromUri]TB_CHARGING obj) { return "ChargingData" + obj.ID; }
得到结果:
如果你不想使用[FromUri]这些在参数里面加特性的这种“怪异”写法,也可以采用先序列化,再在后台反序列的方式。
$.ajax({ type: "get", url: "http://localhost:27221/api/Charging/GetByModel", contentType: "application/json", data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) }, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } } });
[HttpGet] public string GetByModel(string strQuery) { TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery); return "ChargingData" + oData.ID; }
这样在后台得到我们序列化过的对象,再通过反序列化就能得到对象。
数组作为参数
一般get请求不建议将数组作为参数,因为我们知道get请求传递参数的大小是有限制的,最大1024字节,数组里面内容较多时,将其作为参数传递可能会发生参数超限丢失的情况。
$.ajax({ type: "get", url: "http://localhost:27221/api/Charging/FindByModel", contentType: "application/json", data: { strQuery: JSON.stringify({ ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }) }, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } } });
[HttpGet] public string FindByModel(string strQuery) { TB_CHARGING oData = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(strQuery); return "ChargingData" + oData.ID; }
方法名以Get开头,WebApi会自动默认这个请求就是get请求,而如果你以其他名称开头而又不标注方法的请求方式,那么这个时候服务器虽然找到了这个方法,但是由于请求方式不确定,所以直接返回给你405——方法不被允许的错误。
最后结论:所有的WebApi方法最好是加上请求的方式([HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]),不要偷懒,这样既能防止类似的错误,也有利于方法的维护,别人一看就知道这个方法是什么请求。
二、post请求
在WebApi的RESETful风格里面,API服务的增删改查,分别对应着http的post/delete/put/get请求。我们下面就来说说post请求参数的传递方式。
1、基础类型参数
post请求的基础类型的参数和get请求有点不一样,我们知道get请求的参数是通过url来传递的,而post请求则是通过http的请求体中传过来的,WebApi的post请求也需要从http的请求体里面去取参数。
(1)错误的写法
$.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", data: { NAME: "Jim" }, success: function (data, status) { if (status == "success") { $("#div_test").html(data); } } }); [HttpPost] public bool SaveData(string NAME) { return true; }
这是一种看上去非常正确的写法,可是实际情况是:
(2)正确的用法
$.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", data: { "": "Jim" }, success: function (data, status) {} }); [HttpPost] public bool SaveData([FromBody]string NAME) { return true; }
这是一种另许多人头痛的写法,但是没办法,这样确实能得到我们的结果:
我们一般的通过url取参数的机制是键值对,即某一个key等于某一个value,而这里的FromBody和我们一般通过url取参数的机制则不同,它的机制是=value,没有key的概念,并且如果你写了key(比如你的ajax参数写的{NAME:"Jim"}),后台反而得到的NAME等于null。不信你可以试试。
上面讲的都是传递一个基础类型参数的情况,那么如果我们需要传递多个基础类型呢?按照上面的推论,是否可以([FromBody]string NAME, [FromBody]string DES)这样写呢。试试便知。
(1)错误写法
$.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", data: { "": "Jim","":"备注" }, success: function (data, status) {} }); [HttpPost] public bool SaveData([FromBody]string NAME, [FromBody] string DES) { return true; }
得到结果
这说明我们没办法通过多个[FromBody]里面取值,此法失败。
(2)正确用法
既然上面的办法行不通,那我们如何传递多个基础类型的数据呢?很多的解决办法是新建一个类去包含传递的参数,博主觉得这样不够灵活,因为如果我们前后台每次传递多个参数的post请求都去新建一个类的话,我们系统到时候会有多少个这种参数类?维护起来那是相当的麻烦的一件事!所以博主觉得使用dynamic是一个很不错的选择。我们来试试。
$.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", contentType: ''application/json'', data: JSON.stringify({ NAME: "Jim",DES:"备注" }), success: function (data, status) {} }); [HttpPost] public object SaveData(dynamic obj) { var strName = Convert.ToString(obj.NAME); return strName; }
通过dynamic动态类型能顺利得到多个参数,省掉了[FromBody]这个累赘,并且ajax参数的传递不用使用"无厘头"的{"":"value"}这种写法,有没有一种小清新的感觉~~有一点需要注意的是这里在ajax的请求里面需要加上参数类型为Json,即 contentType: ''application/json'', 这个属性。
通过上文post请求基础类型参数的传递,我们了解到了dynamic的方便之处,为了避免[FromBody]这个累赘和{"":"value"}这种"无厘头"的写法。博主推荐所有基础类型使用dynamic来传递,方便解决了基础类型一个或多个参数的传递,示例如上文
2、实体作为参数
(1)单个实体作为参数
上面我们通过dynamic类型解决了post请求基础类型数据的传递问题,那么当我们需要传递一个实体作为参数该怎么解决呢?我们来看下面的代码便知:
$.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", data: { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }, success: function (data, status) {} }); [HttpPost] public bool SaveData(TB_CHARGING oData) { return true; }
得到结果
原理解释:使用实体作为参数的时候,前端直接传递普通json,后台直接使用对应的类型去接收即可,不用FromBody。但是这里需要注意的一点就是,这里不能指定contentType为appplication/json,否则,参数无法传递到后台。我们来看看它默认的contentType是什么:
为了弄清楚原因,博主查了下http的Content-Type的类型。看到如下说明:
- application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式);
- application/json : JSON数据格式
也就是说post请求默认是将表单里面的数据的key/value形式发送到服务,而我们的服务器只需要有对应的key/value属性值的对象就可以接收到。而如果使用application/json,则表示将前端的数据以序列化过的json传递到后端,后端要把它变成实体对象,还需要一个反序列化的过程。按照这个逻辑,那我们如果指定contentType为application/json,然后传递序列化过的对象应该也是可以的啊。博主好奇心重,还是打算一试到底,于是就有了下面的代码:
var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }; $.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", contentType: ''application/json'', data: JSON.stringify(postdata), success: function (data, status) {} }); [HttpPost] public bool SaveData(TB_CHARGING lstCharging) { return true; }
得到结果:
尝试成功,也就是说,两种写法都是可行的。如果你指定了contentType为application/json,则必须要传递序列化过的对象;如果使用post请求的默认参数类型,则前端直接传递json类型的对象即可。
(2)实体和基础类型一起作为参数传递
有些时候,我们需要将基础类型和实体一起传递到后台,这个时候,我们神奇的dynamic又派上用场了。
var postdata = { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }; $.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", contentType: ''application/json'', data: JSON.stringify({ NAME:"Lilei", Charging:postdata }), success: function (data, status) {} }); [HttpPost] public object SaveData(dynamic obj) { var strName = Convert.ToString(obj.NAME); var oCharging = Newtonsoft.Json.JsonConvert.DeserializeObject<TB_CHARGING>(Convert.ToString(obj.Charging)); return strName; }
得到结果:
3、数组作为参数
(1)基础类型数组
var arr = ["1", "2", "3", "4"]; $.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", contentType: ''application/json'', data: JSON.stringify(arr), success: function (data, status) { } }); [HttpPost] public bool SaveData(string[] ids) { return true; }
得到结果:
(2)实体集合
var arr = [ { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }, { ID: "2", NAME: "Lilei", CREATETIME: "1990-12-11" }, { ID: "3", NAME: "Lucy", CREATETIME: "1986-01-10" } ]; $.ajax({ type: "post", url: "http://localhost:27221/api/Charging/SaveData", contentType: ''application/json'', data: JSON.stringify(arr), success: function (data, status) {} }); [HttpPost] public bool SaveData(List<TB_CHARGING> lstCharging) { return true; }
得到结果:
4、后台发送请求参数的传递
上面写了那么多,都是通过前端的ajax请求去做的,我们知道,如果调用方不是web项目,比如Android客户端,可能需要从后台发送http请求来调用我们的接口方法,如果我们通过后台去发送请求是否也是可行的呢?我们以实体对象作为参数来传递写写代码试一把。
public void TestReques() { //请求路径 string url = "http://localhost:27221/api/Charging/SaveData"; //定义request并设置request的路径 WebRequest request = WebRequest.Create(url); request.Method = "post"; //初始化request参数 string postData = "{ ID: \"1\", NAME: \"Jim\", CREATETIME: \"1988-09-11\" }"; //设置参数的编码格式,解决中文乱码 byte[] byteArray = Encoding.UTF8.GetBytes(postData); //设置request的MIME类型及内容长度 request.ContentType = "application/json"; request.ContentLength = byteArray.Length; //打开request字符流 Stream dataStream = request.GetRequestStream(); dataStream.Write(byteArray, 0, byteArray.Length); dataStream.Close(); //定义response为前面的request响应 WebResponse response = request.GetResponse(); //获取相应的状态代码 Console.WriteLine(((HttpWebResponse)response).StatusDescription); //定义response字符流 dataStream = response.GetResponseStream(); StreamReader reader = new StreamReader(dataStream); string responseFromServer = reader.ReadToEnd();//读取所有 Console.WriteLine(responseFromServer); }
当代码运行到request.GetResponse()这一句的时候,API里面进入断点
尝试成功。
三、put请求
WebApi里面put请求一般用于对象的更新。它和用法和post请求基本相同。同样支持[FromBody],同样可以使用dynamic。
1、基础类型参数
$.ajax({ type: "put", url: "http://localhost:27221/api/Charging/Update", contentType: ''application/json'', data: JSON.stringify({ ID: "1" }), success: function (data, status) {} }); [HttpPut] public bool Update(dynamic obj ) { return true; }
2、实体作为参数
和post请求相同。
3、数组作为参数
和post请求相同。
四、delete请求
顾名思义,delete请求肯定是用于删除操作的。参数传递机制和post也是基本相同。下面简单给出一个例子,其他情况参考post请求。
var arr = [ { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" }, { ID: "2", NAME: "Lilei", CREATETIME: "1990-12-11" }, { ID: "3", NAME: "Lucy", CREATETIME: "1986-01-10" } ]; $.ajax({ type: "delete", url: "http://localhost:27221/api/Charging/OptDelete", contentType: ''application/json'', data: JSON.stringify(arr), success: function (data, status) {} }); [HttpDelete] public bool OptDelete(List<TB_CHARGING> lstChargin) { return true; }
博文的一点评论:
dynamic虽然很巧妙地解决了从请求body中获取参数。但是这样不利于生成api文档。
ps:一般都是用pagehelp等工具,自动读取元数据,生成api文档的。
如果用dynamic的话,生成的文档就只有一个dynamic类型的参数,这样api调用者就无法明确api的参数了。
还有接收参数定义为dynamic类型的话,后续维护或升级太麻烦。
如果是post操作。文中介绍了两种传递实体参数的方法
第一种:
1 |
|
不需要指定contentType。
第二种:
1 |
|
需要指定contentType:"application/json"。两种方式后台都可以得到实体。不知道你的Json字符串是怎么得到的,是拼的字符串?建议使用JSON.stringify( { ID: "1", NAME: "Jim", CREATETIME: "1988-09-11" })这种方式得到json字符串。
AndroidAsyncHttp 临时修复 JsonHttpResponseHandler 避免死循环
由于 AndroidAsyncHttp 1.4.4 的 JsonHttpResponseHandler 存在死循环的 BUG,1.4.5 版本发布不知道要何时,所以只能临时替换该类来修复这个错误。
Android开源库loopj的android-async-http的 JsonHttpResponseHandler 存在死循环GC_CONCURRENT
package com.ai9475.extend;
import com.ai9475.meitian.AppManager;
import com.ai9475.meitian.R;
import com.loopj.android.http.JsonHttpResponseHandler;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.util.Log;
import org.apache.http.Header;
import org.apache.http.HttpStatus;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import java.io.UnsupportedEncodingException;
/**
* 复写 AndroidAsyncHttp 1.4.4 开源库的 JsonHttpResponseHandler 类
* 当 1.4.5 released 后失效
*
* Created by ZHOUZ on 2014/3/22.
*/
public class ZJsonHttpResponseHandler extends JsonHttpResponseHandler
{
private static final String LOG_TAG = "JsonHttpResponseHandler";
/**
* Returns when request succeeds
*
* @param statusCode http response status line
* @param headers response headers if any
* @param response parsed response if any
*/
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
}
/**
* Returns when request succeeds
*
* @param statusCode http response status line
* @param headers response headers if any
* @param response parsed response if any
*/
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
}
/**
* Returns when request failed
*
* @param statusCode http response status line
* @param headers response headers if any
* @param throwable throwable describing the way request failed
* @param errorResponse parsed response if any
*/
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
}
/**
* Returns when request failed
*
* @param statusCode http response status line
* @param headers response headers if any
* @param throwable throwable describing the way request failed
* @param errorResponse parsed response if any
*/
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) {
}
@Override
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
final AlertDialog.Builder dialog = new AlertDialog.Builder(AppManager.ActivityManager.current());
dialog.setIcon(android.R.drawable.ic_dialog_info);
dialog.setTitle(R.string.app_error);
dialog.setMessage(responseString);
dialog.setNegativeButton(R.string.sure,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
dialog.show();
}
@Override
public void onSuccess(int statusCode, Header[] headers, String responseString) {
}
@Override
public final void onSuccess(final int statusCode, final Header[] headers, final byte[] responseBytes) {
if (statusCode != HttpStatus.SC_NO_CONTENT) {
new Thread(new Runnable() {
@Override
public void run() {
try {
final Object jsonResponse = parseResponse(responseBytes);
postRunnable(new Runnable() {
@Override
public void run() {
if (jsonResponse instanceof JSONObject) {
onSuccess(statusCode, headers, (JSONObject) jsonResponse);
} else if (jsonResponse instanceof JSONArray) {
onSuccess(statusCode, headers, (JSONArray) jsonResponse);
} else if (jsonResponse instanceof String) {
onFailure(statusCode, headers, (String) jsonResponse, new JSONException("Response cannot be parsed as JSON data"));
} else {
onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null);
}
}
});
} catch (final JSONException ex) {
postRunnable(new Runnable() {
@Override
public void run() {
onFailure(statusCode, headers, ex, (JSONObject) null);
}
});
}
}
}).start();
} else {
onSuccess(statusCode, headers, new JSONObject());
}
}
@Override
public final void onFailure(final int statusCode, final Header[] headers, final byte[] responseBytes, final Throwable throwable) {
if (responseBytes != null) {
new Thread(new Runnable() {
@Override
public void run() {
try {
final Object jsonResponse = parseResponse(responseBytes);
postRunnable(new Runnable() {
@Override
public void run() {
if (jsonResponse instanceof JSONObject) {
onFailure(statusCode, headers, throwable, (JSONObject) jsonResponse);
} else if (jsonResponse instanceof JSONArray) {
onFailure(statusCode, headers, throwable, (JSONArray) jsonResponse);
} else if (jsonResponse instanceof String) {
onFailure(statusCode, headers, (String) jsonResponse, throwable);
} else {
onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null);
}
}
});
} catch (final JSONException ex) {
postRunnable(new Runnable() {
@Override
public void run() {
onFailure(statusCode, headers, ex, (JSONObject) null);
}
});
}
}
}).start();
} else {
Log.v(LOG_TAG, "response body is null, calling onFailure(Throwable, JSONObject)");
onFailure(statusCode, headers, throwable, (JSONObject) null);
}
}
/**
* Returns Object of type {@link JSONObject}, {@link JSONArray}, String, Boolean, Integer, Long,
* Double or {@link JSONObject#NULL}, see {@link org.json.JSONTokener#nextValue()}
*
* @param responseBody response bytes to be assembled in String and parsed as JSON
* @return Object parsedResponse
* @throws org.json.JSONException exception if thrown while parsing JSON
*/
protected Object parseResponse(byte[] responseBody) throws JSONException {
if (null == responseBody)
return null;
Object result = null;
//trim the string to prevent start with blank, and test if the string is valid JSON, because the parser don''t do this :(. If Json is not valid this will return null
String jsonString = getResponseString(responseBody, getCharset());
if (jsonString != null) {
jsonString = jsonString.trim();
if (jsonString.startsWith("{") || jsonString.startsWith("[")) {
result = new JSONTokener(jsonString).nextValue();
}
}
if (result == null) {
result = jsonString;
}
return result;
}
/**
* Attempts to encode response bytes as string of set encoding
*
* @param charset charset to create string with
* @param stringBytes response bytes
* @return String of set encoding or null
*/
public static String getResponseString(byte[] stringBytes, String charset) {
try {
return stringBytes == null ? null : new String(stringBytes, charset);
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Encoding response into string failed", e);
return null;
}
}
}
现在如果再出现 HTTP 500 或其他服务端错误(输出非 JSON 字符串)时将会直接弹出服务端页面内容的对话框方便调试了,现在只能这样了,等新版本发布后再转换下吧!
关于从BaseHTTPHandler解析http GET和POST参数?和http详解的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于.net-4.0 – 从自定义IHttpHandler调用MvcHttpHandler.ExecuteRequest时出错、ajax 参数传递之 [HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete] 请求、ajax参数传递之[HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete]请求、AndroidAsyncHttp 临时修复 JsonHttpResponseHandler 避免死循环的相关知识,请在本站寻找。
本文标签: