zoukankan      html  css  js  c++  java
  • WebApi Post 后台无法获取参数的解决方案

    事件回放:

    之前一段时间,公司里前端用的Angularjs 发送http请求也是用的ng的组件,后台是.Net的WebApi

    前端

    var data = {
        PArgs: {
            PageIndex: 0,
            PageSize: 8,
            RowsCount: 0
        }
    };
    
    $http.post("/Api/Test/ABC", data).success(function (data) {
        console.log(data)
    });

    后台接收

    using SignalRDemo.VModel;
    using System.Web.Http;
    
    namespace SignalRDemo.Api
    {
        public class TestController : ApiController
        {
            [HttpPost]
            public object ABC([FromBody]MMCourse model)
            {
                return model;
            }
        }
    }

    具体的Model是这样子的

    using System;
    
    namespace SignalRDemo.VModel
    {
        public class MMCourse : BaseModel
        {
            //上传分页
            public PagerArgs PArgs { set; get; }
        }
    
        public sealed class PagerArgs
        {
            /// <summary>
            /// 分页
            /// </summary>
            /// <param name="pageIndex">每页数据条数</param>
            /// <param name="pageSize">数据总行数</param>
            public PagerArgs(int pageIndex, int pageSize)
            {
                this.PageIndex = pageIndex;
                this.PageSize = pageSize;
            }
    
            /// <summary>
            /// 当前页索引
            /// </summary>
            public int PageIndex { get; set; }
    
            /// <summary>
            /// 每页数据条数
            /// </summary>
            public int PageSize { get; set; }
        }
    }
    Model

    流程就是后台建好实体类,创建接口

    前台指定要访问的接口,传入与后台接收参数的实体类结构相同的对象,后台就能接收到这个数据。运行正常。


    后来  某一新建页面  前台没有使用Angularjs,而是用的jQuery,访问同一接口,突然发现 后台接收到的参数一直是null。

    WebApi Post方式 怎么会无法获取参数呢?

    通过查看控制台的http请求和后台的数据,经过不断的摸索,依次发现几个解决方法,也伴随着一些诡异事件:

    方案①

    首先 后台肯定是成功接收到了请求的,但是由于某种原因,接口方法的输入参数没有值。

    初步判断跟类型转换有关,将接收类型改为JObject,就能收到数据了,然后再序列化->反序列化

    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using SignalRDemo.VModel;
    using System.Web.Http;
    
    namespace SignalRDemo.Api
    {
        public class TestController : ApiController
        {
            [HttpPost]
            public object ABC([FromBody]JObject model)
            {
                return JsonConvert.DeserializeObject<MMCourse>(JsonConvert.SerializeObject(model));
            }
        }
    }

     方案②经过修改参数发现,在不改动后台的情况下,如果参数是

    var data = {
        A:1
    };

     后台收到的数据结构是这样的

    {
     Pargs:{
      PageIndex:0,
      PageSize:0
     }
    }

    不管怎样,数据还是能传递过去,只是webapi将参数转换的时候应该是出了问题。

    回头仔细看了一下后台实体类,发现PagerArgs类有一个构造函数 还是要有两个参数的。试着添加了一个无参构造,发现数据能够正常获取了!

    这个如果要深究的话  就要研究webapi底层对字符串的反序列化处理了,暂时忽略。

     方案③

    虽然通过上面两种方式可以迂回解决问题,但是心里还纠结着一个问题:为毛用Ng的$http.post一直没事,换了jQuery.post就发生这么多事?

    开始对比两种方式的请求信息

    点击数据上方的【view source】 查看发送的字符串

    ng :  

    {"PArgs":{"PageIndex":0,"PageSize":8,"RowsCount":0}}

    jq:

    PArgs%5BPageIndex%5D=0&PArgs%5BPageSize%5D=8&PArgs%5BRowsCount%5D=0
    decode之后是
    PArgs[PageIndex]=0&PArgs[PageSize]=8&PArgs[RowsCount]=0

    ng发送的数据跟预想中是一样的  跟发送的对象保持一直的json结构。

    但是   jq发送的怎么会成了这种模样?此外  Request Payload跟Form Data又是什么?是Content-Type的区别引起的这些么?

    通过查看jq.ajax的Api 找到下面一段

    说的就是  如果使用的是post  默认的contentType是“application/x-www-form-urlencoded;charset=UTF-8“,

    如果contentType是"..form..",则发送数据的是Form Data
    如果是”application/json“ ,则是Request Payload。

    而使用这种内容类型时,会把数据用$.param()转换一次之后再发送。

    跟用之前用jq发送的数据内容完全匹配,就是这个原因了。

    那这样处理起来就简单了,只需要发送数据前设置contentType="application/json;charset=UTF-8"就可以了。

    还有一点要注意的是 ajax是不会发送对象的  最终都要转换成字符串。所以发送的时候需要人为的处理一下。

    var data = {
        PArgs: {
            PageIndex: 0,
            PageSize: 8,
            RowsCount: 0
        }
    };
    
    $.ajaxSetup({
        contentType: "application/json;charset=UTF-8"
    })
    
    $.post("/Api/Test/ABC", JSON.stringify(data), function (rst) {
        //TODO
    }, "json");

     或者

    $.ajax({
        url: "/Api/Test/ABC",
        dataType: "json",
        type: "post",
        contentType: "application/json;charset=UTF-8",
        data: JSON.stringify(data),
        success: function (rst) {
            console.log(rst);
        }
    })
  • 相关阅读:
    mysql那些事(1)手机号与座机号码如何存储
    分享一个PHP调用RestFul接口的函数
    php sprintf用法
    HTTP状态码详解
    PHP随机生成中国人姓名的类
    PHP计算两组经纬度坐标之间的距离
    PHP根据经纬度获取在范围坐标的数据
    PHP 利用QQ邮箱发送邮件「PHPMailer」
    PHP中利用PHPMailer配合QQ邮箱实现发邮件
    修改PHP上传文件大小限制
  • 原文地址:https://www.cnblogs.com/TiestoRay/p/5032202.html
Copyright © 2011-2022 走看看