原生Ajax向.NetCore3.X WebApi 傳參
本文基于瀏覽器原生的Ajax請求+Asp.NetCore3.X WebApi進行講解。其他環(huán)境其實本質上也是類似的。
一、Ajax 準備工作。
1. 創(chuàng)建Ajax請求對象
function CreateAjaxXHR() {
? ?//創(chuàng)建核心對象
? ?xmlhttp = null;
? ?if (window.XMLHttpRequest) {
? ? ? ?xmlhttp = new XMLHttpRequest();
? ?} else if (window.ActiveXObject) {
? ? ? ?//for IE6, IE5
? ? ? ?xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
? ?}
? ?return xmlhttp;
}
2.Ajax基本請求模式
//抽取數據代碼
document.getElementById('getQuestion').addEventListener('click', function () {
? ?let xmlhttp = CreateAjaxXHR();
? ?if (xmlhttp === null) {alert('不支持Ajax!'); return; }
? ?xmlhttp.onerror = function (err) {alert(xmlhttp.responseText); };
? ?//編寫回調函數
? ?xmlhttp.onreadystatechange = function () {
? ? ? ?if (xmlhttp.readyState === 4) {
? ? ? ? ? ?//請求成功的處理
? ? ? ? ? ?if (xmlhttp.status === 200) {
? ? ? ? ? ? ? //ToDo:在此進一步處理相關業(yè)務邏輯
? ? ? ? ? ?}
? ? ? ? ? ?else {alert(xmlhttp.responseText);}
? ? ? ?} else
? ? ? ?{
? ? ? ? ? ?//請求失敗的相關處理
? ? ? ? ? ? alert(xmlhttp.responseText);
? ? ? ?}
? ?};
? ?//設置Ajax請求方式、數據格式,準備數據內容、發(fā)送數據
? ?xmlhttp.open('post', 'Api/controller', true); ? //true:表異步
? ?xmlhttp.setRequestHeader('content-type', 'application/json'); //指明數據格式
? ?let willSentData={x:1,y:2}; ?//準備數據,應與上一行代碼相匹配
? ?xmlhttp.send(willSentData); ?//發(fā)送數據
});
本文主要講解在Ajax請求過程中的轉參方式(前端發(fā)送數據與后端接收數據),因此前臺的Ajax請求重點主要集中在以下幾行代碼上。
? ?//設置Ajax請求方式、數據格式,準備數據內容、發(fā)送數據
? ?xmlhttp.open('post', 'Api/controller', true); ?
? ?xmlhttp.setRequestHeader('content-type', 'application/json');
? ?let willSentData={x:1,y:2}; ?
? ?xmlhttp.send(willSentData);
二、Get 請求
該請求方式特點如下:
參數通過url傳遞(所以不夠安全,容易泄密)
傳遞的參數是有長度限制(一般是4K)
請求的Url會被瀏覽器緩存
發(fā)送請求時,瀏覽器會把http header和data一并發(fā)送出去,服務器響應200(返回數據),因此Get請求只會產生一個tcp數據包。(這一點比Post方式高效)
根據需要(比如有中文或特殊字符)需對請求地址進行url編碼(也只有此一種編碼方式)。
無參模式
前臺:
? ?xmlhttp.open('get', 'Api/controller', true); ?
? ?xmlhttp.send();
后臺:
? ?[HttpGet]
? ?public string Get()
? ?{? ? ? ?return "ok"? ?? ?}
小提示:如果后臺有多個Get方法,可通過 [httpGet屬性] 來指定前臺訪問的路由地址,如下所示(此方式也適應 [httpPost屬性] 等):
后臺:
? ?[HttpGet]
? ?public string Get1()
? ?{? ? ? ?return "ok"? ?}
? ?[HttpGet("Get2")]
? ?public string Get2()
? ?{? ? ? ?return "ok"? ?}
前臺:
? ?xmlhttp.open('get', 'Api/controller', true); ? ? ? //將訪問 Get1方法
? ?xmlhttp.open('get', 'Api/controller/Get2', true); ?//將訪問 Get2方法
有參模式(又有兩種方式)
(1)拼接參數模式。
注意:后臺方式參數的名稱與前臺傳遞的參數名稱可以不同,但個數、類型必須相同。否則將報“ 415 (Unsupported Media Type) ”錯誤
前臺:
? ?xmlhttp.open('get', 'Api/controller?key1=value1&&key2=2', true); ?
? ?xmlhttp.send();
后臺:
? ?[HttpGet]
? ?public string Get(string key1,int key2 )
? ?{ ? ? ?
? ? ? ?return "ok"
? ?}
(2)路由參數模式
前臺:
? ?xmlhttp.open('get', 'Api/controller/value1/2', true);
? ?xmlhttp.send();
后臺:
? ?[HttpGet ("{key1}/{key2}")]
? ?public string Get(string key1,int key2 )
? ?{ ? ? ?
? ? ? ?return "ok"
? ?}
三、Post 請求
該請求方式特點如下:
參數放在request body中(對.Net core WebApi來說,要視具體情況)
傳遞的參數無長度限制(但一般大于 2G 時,要進行相關設置)
請求的Url不會被瀏覽器緩存
發(fā)送請求時,瀏覽器會先發(fā)送 http header,收到響應 100 continue 時,再發(fā)送data請求數據,服務器響應200(返回數據),因此Post請求會產生二個tcp數據包。
根據需要可對數據進行多種編碼,包括url編碼。
無參模式
前臺:
? ?xmlhttp.open('Post', 'Api/controller', true); ?
? ?xmlhttp.send();
后臺:
? ?[HttpPost]
? ?public string Post()
? ?{
? ? ? ?return "ok"
? ?}
有參模式(根據前臺參數類型不同,后臺接收方式不同)
(1)Json格式數據。
注意:
后臺數據模型類中的屬性數據類型,必須與前臺待發(fā)送數據中的相應相屬性的數據類型完全一致,否則會報 400 (Bad Request) 錯誤。
前臺在發(fā)送數據前必須序列化為 JSON 字符串,否則會報 400 (Bad Request) 錯誤。
前臺:
? ?xmlhttp.open('post', 'Api/controller', true); ?
? ?xmlhttp.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
? ?let WillSentData={key1:"vaule1",key2:2}; ?
? ?WillSentData = JSON.stringify(WillSentData); ?//序列化為字符串
? ?xmlhttp.send(WillSentData);
后臺:
? ?[HttpPost]
? ?public string Post([FromBody] DataModel P_Data )
? ?{ ?
? ? ? ?//說明:DataModel 是一個類,其中有 string key1 和 int key2 兩個屬性。 ? ? ? ?
? ? ? ?return "ok"
? ?}
(2)FormData格式數據
注意:
通過該方式,可以上傳文件及其他相關數據;
后臺接收時,需通過鍵名稱進行查詢具體參數值,其類型均為 Microsoft.Extensions.Primitives.StringValues 即相當于字符串類型。
前臺: ? ??
????????xmlhttp.open('post', 'Api/controller', true); ? ? ??
????????//xmlhttp.setRequestHeader('Content-Type', 'multipart/form-data;charset=utf-8'); ? ?
????????//理論上來說,應當加上上一句,但實測過程中,如使用上句代碼會報 400 (Bad Request) 錯誤,不知是不是Bug。不使用反而可以正常運行,且通過調試查詢 Content-Type 的值就是multipart/form-data。 ? ? ?
????????let WillSentData=new FormData();? ? ?
????????WillSentData.append('UpFileName', InputFileElement.files[0]);? ? ? ?????????????
????????WillSentData.add{(key1,"vaule1");
? ? ? ? WillSentData.add{(key2",2);? ? ?
? ? ? ? xmlhttp.send(WillSentData);?
后臺: ? ?
[HttpPost] ? ?
public string Post[FromForm] IFormCollection P_Data ) ? ?
?{ ? ? ? ? ?
????????//說明:IFormCollection 是表單(From)內各元素的集合。 ? ? ? ?
????????string key1value=P_Data["key1"]; ? ? ? ?
????????string key2Value=P_Data["key2"]; //接收到的內容全部為字符串類型數據 ? ? ? ?
????????FormFile FirstFile = P_Data.Files[0] as FormFile; ?//接收到的文件 ? ? ? ?
????????return "ok" ? ?
}
四、Patch 請求
特點:
參數放在request body中
具體方式,請參考 Post請求
五、Put 請求
特點:
參數放在request body中
具體方式,請參考 Post請求
六、Delete 請求
特點:
參數通過url傳遞
具體方式,請參考 Get請求
本文在GitHub地址: