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);
    }
})

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM