GVKun编程网logo

从BaseHTTPHandler解析http GET和POST参数?(http详解)

38

本文将分享从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详解)

从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时出错

.net-4.0 – 从自定义IHttpHandler调用MvcHttpHandler.ExecuteRequest时出错

我有一个自定义的IHttpHandler,调用MvcHttpHandler,如 this answer所述.

它在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不会出现任何问题.

有谁知道这里发生了什么,以及如何解决它?

解决方法

我相信你需要使用httpContext.Server.TransferRequest和MVC更新.

看到这个问题:MVC3 Application Inside Webforms Application Routing is throwing a HttpContext.SetSessionStateBehavior Error in IIS7.5

ajax 参数传递之 [HttpGet]/[HttpPost]/[HttpPut]/[HttpDelete] 请求

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参数传递之[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字符串。

AndroidAsyncHttp 临时修复 JsonHttpResponseHandler 避免死循环

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 避免死循环的相关知识,请在本站寻找。

本文标签: