一些簡單的Post方式WebApi接收參數和傳遞參數的方法及總結


原文地址:https://www.zhaimaojun.top/Note/5475297(我自己的博客網站)

各種Post方式上傳參數到服務器,服務器接收各種參數的示例

webapi可以說是很常用了,內容也很多,get方式用的多而且很簡單,沒有說的必要了,但是post方式中,數據從數據體中提取是總是會遇到一些妖魔現象。對此,就我知道的我說一些吧。

作為懶漢,一切繁瑣的代碼,邏輯,都是累贅,都是看不順眼的,拖泥帶水的代碼,邏輯就像強迫症眼里的不規則擺放,總是要解決掉心里才能舒坦的懶。天天幻想着一條代碼解決所有問題~

最近有點想注冊個bilibili的up主發點代碼講解的視頻,我想我能將的比較細致,碼字太累了,不符合懶漢的生活習慣,就這短短的文章也是碼了一下午才寫完的,所以還是講話來的快,還不耽誤玩游戲。

webapi的url組成我就不詳細說了,一般都是http://XXX/api/控制器名?參數名=參數值&參數名=參數值

第一種:

接收參數:
[httppost] public string Get(string p1,[frombody]string p2){ return p1+p2; }
c#發送參數:
var p2 = "param2";//p2是需要post傳輸的 var url = "http://XXX/api/XXX?p1=param1";//p2是來自於post體,所以不再url中 var req= (HttpWebRequest)WebRequest.Create(url); req.Method = "POST"; req.ContentType = "application/x-www-form-urlencoded";//你沒有看錯,就是這個 var bts = Encoding.Utf8.GetBytes("="+p2);//划重點!!post方式中application/x-www-form-urlencoded傳輸方式下,frombody的參數只能有一個!而在body中你要是用key=value方式傳遞參數,那么接收端收到的全都是null。 req.ContentLenth = bts.Lenth;//划重點!!post方式必須設置這個值 var st = req.GetResquestStream(); st.Write(bts,0,bts.Lenth);//划重點!!post方式必須要往body中寫入數據 var res= (HttpWebResponse)req.GetResponse();
ajax提交參數:
var url = "http://XXX/api/XX?p1=param1" var p2 = "param2" $.post(url, "="+p2, function(res){ alert(res); });
微信小程序提交參數(JavaScript):
var p2 = "param2"; wx.request({ url: 'http://XXX/api/XX?p1=param1', method: 'POST', header: {'content-type': 'application/x-www-form-urlencoded'},//或者不寫這行 data: "=" + p2, success(re){ console.log(re); } });
這種方式的注意點:
很早前我學習api的時候就遇到了參數始終為null的苦惱,當時也沒有相關的資料可以查閱,百度到的內容都七七八八,都說不到重點上,最后不知道在哪個網站上看見了有個人也是同樣的問題,有人提到說是=號前面不要參數名,我嘗試了,還真就解決問題了,於是我寫了哪一篇博文,到現在三年多了,被好多人轉載了。說明大家都被這個問題折磨了很久啊哈哈哈,其實要點很簡單,就是body中只要一個參數的值,且=號開始,=號前面不寫參數名,=號后面的所有內容都會被讀取為唯一的那個frombody的參數內容。就是這樣的。要知道api只能有一個參數是frombody的!

第二種:

接收參數:
[httppost] public string Post(string p1){ var p2 = HttpContext.Current.Request.Form["p2"]; var p3 = HttpContext.Current.Request.Form["p3"]; if(HttpContext.Current.Request.Files.Lenth > 0){ var fs = HttpContext.Current.Request.Files[0]; fs.SaveAs(HttpContext.Current.Server.MapPath("~/data.txt")); } return p1+p2+p3;//上傳的混合參數 }

c#發送參數:

        private string UploadFileAndParams(string serverIp, int serverPort, string rowurl, string filename, Dictionary<string, string> otherparams) { try { //打開socket連接 Socket httpsocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); httpsocket.Connect(serverIp, serverPort); //計算得出總的一個請求 //請求的頭部 string httprequestheader = "POST " + rowurl + " HTTP/1.1\r\n"; httprequestheader += "Host: " + serverIp + ":" + serverPort + "\r\n"; //httprequestheader += "Content-Length: " + "\r\n";//計算並添加數據長度,這里的數據長度是總的長度 httprequestheader += "Content-Type: multipart/form-data; boundary=OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp\r\n"; httprequestheader += "Connection: Keep-Alive\r\n"; //發送文件 string httpFileheader = "--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp\r\n"; httpFileheader += "Content-Disposition: attachment; name=text; filename=" + Path.GetFileName(filename) + "\r\n"; httpFileheader += "Content-Type: application/octet-stream\r\n"; httpFileheader += "Content-Transfer-Encoding: binary\r\n"; httpFileheader += "\r\n"; byte[] Bfileheader = Encoding.UTF8.GetBytes(httpFileheader); //這里需要發送文件的內容,二進制 FileStream localfile = new FileStream(filename, FileMode.Open); //發送其他參數 var lBParamheaders = new List<byte[]>(); foreach (var item in otherparams) { string paramstr = "--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp\r\n"; paramstr += "Content-Disposition: form-data; name=" + item.Key + "\r\n"; paramstr += "Content-Type: text/plain; charset=UTF-8\r\n"; paramstr += "\r\n"; paramstr += item.Value + "\r\n"; lBParamheaders.Add(Encoding.UTF8.GetBytes(paramstr)); } byte[] Bendbody = Encoding.UTF8.GetBytes("--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp--\r\n"); //統計總長度 long lenth = Bfileheader.Length + localfile.Length + Bendbody.Length + 2; foreach (var item in lBParamheaders) lenth += item.Length; httprequestheader += "Content-Length: " + lenth + "\r\n";//計算並添加數據長度,這里的數據長度是總的長度 httprequestheader += "\r\n"; byte[] Brequestheader = Encoding.UTF8.GetBytes(httprequestheader); //開始發送請求 string sv = Encoding.UTF8.GetString(Brequestheader); httpsocket.Send(Brequestheader);//發送頭 sv += Encoding.UTF8.GetString(Bfileheader); httpsocket.Send(Bfileheader);//發送文件頭 //發送文件 for (long i = 0; i < localfile.Length;) { int len = ((localfile.Length - i) &gt; 30000) ? 30000 : (int)(localfile.Length - i); byte[] bt = new byte[len]; localfile.Read(bt, 0, len); sv += Encoding.UTF8.GetString(bt); httpsocket.Send(bt); i += len; } sv += "\r\n"; httpsocket.Send(Encoding.UTF8.GetBytes("\r\n")); //發送其他參數 foreach (var item in lBParamheaders) { sv += Encoding.UTF8.GetString(item); httpsocket.Send(item); } sv += Encoding.UTF8.GetString(Bendbody); httpsocket.Send(Bendbody); //等待服務器返回結果: byte[] result = new byte[30000]; int reslen = httpsocket.Receive(result); //處理並返回結果 string resultstr = Encoding.UTF8.GetString(result, 0, reslen); int idex = resultstr.IndexOf("\r\n\r\n"); string resstr = resultstr.Substring(idex); localfile.Close(); httpsocket.Close(); return resstr; } catch (Exception ex) { return ex.Message; } } //使用: var pms = new Dictionary<string, string>(); pms.Add("p2","param2"); pms.Add("p3","param3"); var result = UploadFileAndParam("192.168.1.1",8088,"/api/XX?p1=param1","指定一個本地要上傳的文件名",pms);

ajax提交參數(html):

    <form method="post" action="/api/XXX?p1=param1"> <div class="form-group input-group"> <input name="p2" class="form-control" value="param2" type="text" /> <input name="p3" class="form-control" value="param3" type="text" /> <input name="文件名不重要" class="form-control" type="file" accept="image/png, image/jpeg(這里要寫上傳的文件的類型)" /> <span class="input-group-btn"> <button class="btn btn-default" type="submit"> <span class="glyphicon glyphicon-search"></span>上傳 </button> </span> </div> </form>

微信小程序提交參數(JavaScript):

wx.chooseImage({
  success (res) {
    const tempFilePaths = res.tempFilePaths wx.uploadFile({ url: 'http://xxx/api/XX?p1=param1', filePath: tempFilePaths[0], name: '文件名', formData: { 'p2': 'param2', 'p3': 'param3' }, success (res){ console.log(res); } }) } })

這種方式的注意點:

這就是傳統的mvc的頁面提交方式,是帶文件的提交方式,這里要注意的就是,c#部分我貼的代碼其實不是http請求,而是socket連接,也就是說,他不限制平台,比如一個單片機,接上一個能夠聯網且創建socket的模塊,不需要實現http協議,就可以直接將數據發送給服務器,然后收到服務器的回復!市場上常用的nbiot模塊或者以太網模塊或者wifi模塊,只要能連接服務器並且創建socket連接,就可以,我當初就是拿這套代碼改成c語言版本后跑在單片機上,通過bc35模塊連接雲服務器的。

第三種:

接收參數:

public struct SomeData{//struct的名稱其實不重要 public string p2{get;set;}//注意,get;set;這種屬性很重要,如果不是屬性很可能參數一直為null! public int p3{get;set;} } [httppost] public string Get(string p1,[frombody]SomeData sd){//這里的參數名不重要 return p1+sd.p2+sd.p3;//所有的混合參數 }

c#發送參數:

//代碼中使用到了Newtonsoft.Json包,請自行下載安裝 public string PostData(string url, object o) { try { var dts = Newtonsoft.Json.JsonConvert.SerializeObject(o);//先將object轉為json字符串 var data = Encoding.UTF8.GetBytes(dts);//再將字符串轉換為byte[] var hr= (HttpWebRequest)WebRequest.Create(url); hr.Method = "POST"; hr.ContentType = "application/json"; hr.ContentLength = data.Length; using (var rs = hr.GetRequestStream()) rs.Write(data, 0, data.Length); using (WebResponse hp = hr.GetResponse()) using (Stream s = hp.GetResponseStream()) { var res = new StreamReader(s).ReadToEnd(); return res; } } catch (Exception) { return null; } } //使用: var result = PostData("http://XXX/api/XX?p1=param1",new { p2 = "param2", p3 = 333 });

ajax提交參數:

var url = "http://XXX/api/XX?p1=param1" var pms = { p2 : "p2", P3 : 333, } $.post(url, pms, function(res){ alert(res); });

微信小程序提交參數(JavaScript):

var pms = { p2 : "param2", p3 : 333, } wx.request({ url: 'http://XXX/api/XX?p1=param1', method: 'POST', header: {'content-type': 'application/json;charset=UTF-8'}, data: pms, success(re){ console.log(re); } });

這種方式的注意點:

這種方式就是現在很流行的json數據通訊方式,這種方式下,微信小程序,ajax等都支持,且代碼簡潔,比較常用,但是也要注意,就是struct中的內容最好都是get;set;的屬性,我之前用變量的方式好像也能收到參數,但是后來又發現不能收到參數,也可能是不同的.net版本導致的,服務器端需要安裝Newtonsoft.Json包,一般都會自帶有一個舊版本的包,最好還是更新一下。c#傳遞參數時就必須要用到Newtonsoft.Json包的,如果是wpf項目是不會自帶這個包的。安裝這個包也很簡單,就是到nuget包管理器中搜索然后安裝就行了。

各種服務器返回數據后本地解析數據的示例

第一種:

服務器返回:

public string Get(string p1){//返回值就是普通的常用的類型,比如string,int,long,double,等等 return p1; }

c#解析數據:

var req= (HttpWebRequest)WebRequest.Create("http://xxx/api/xx?p1=1"); var res= (HttpWebResponse)req.GetResponse(); var result = int.TryParse(res, out var v) ? v : default;//非string就用指定的類型TryParse,如果是string,注意了,其中會包含兩個雙引號,所以結果應該需要replace比如: var result = res.Trim('\"');//res.Replace("\"",string.Empty);

微信小程序/ajax解析數據:

wx.request({
    url: 'http://XXX/api/XX?p1=param1', success(re){ console.log(re.data);//re基本都是字符串類型,所以直接可以用來判斷,如果服務器返回的是string類型,則注意re.data中會有兩個雙引號一前一后,需要去除掉 } });

這種方式的注意點:

這種方式對微信ajax等平台不友好,數據返回比較單一,且都是字符串,需要自己去解析內容,比較不方便,雖然服務器返回數據方便,但是對數據的使用者來說造成了麻煩。

第二種:

服務器返回:

public IHttpActionResult Get(string p1){//學過mvc的應該很眼熟吧,沒錯,就是和mvc的返回方式是一樣的! return Json(new { dt1 = "data1", dt2 = 2345 });//這是返回的是純json,可以返回任意的對象,json中包括了對象的所有可讀的屬性。當然,你也可以返回數組,字典,List,struct等等你想返回的東西 var fp = HttpContent.Current.Server.MapPath("~/file/p1.jpg"); return File(fp,MimeMapping.GetMimeMapping(fp),"當我們點擊下載時顯示的名稱.jpg");//這是返回任意的文件,其他更多的方式可參考mvccontroler }

c#解析數據:

//服務器返回文件時可以直接下載就可以了: var result = new WebClient().DownloadFile ("http://xxx/api/xx?p1=","指定一個本地的保存文件的地址"); //如果服務器返回的是一個對象,數組,struct,List等時: public struct SomeData{ public string dt1{get;set;} public int dt2{get;set;} } var hr= (HttpWebRequest)WebRequest.Create("http://xxx/api/xx?p1=1"); var hp = hr.GetResponse(); var s = hp.GetResponseStream(); var res = new StreamReader(s).ReadToEnd(); try{ return Newtonsoft.Json.JsonConvert.DeserializeObject<SomeData>(res); } catch { return default; }//返回值就是一個struct,當然,上面的SomeData可以是其他的類型,如果json反序列化失敗則會拋出異常,然后返回default,返回一個缺省的值。 

微信小程序/ajax解析數據:

//如果是文件: wx.downloadFile({//(摘自微信公眾平台:https://developers.weixin.qq.com/miniprogram/dev/api/network/download/wx.downloadFile.html) url: 'http://xxx/api/xx?p1=', //僅為示例,並非真實的資源 success (res) { // 只要服務器有響應數據,就會把響應內容寫入文件並進入 success 回調,業務需要自行判斷是否下載到了想要的內容 if (res.statusCode === 200) { wx.playVoice({ filePath: res.tempFilePath }) } } }) //如果返回的是純json內容: wx.request({ url: 'http://XXX/api/XX?p1=param1', success(re){ console.log(re.data); if(re.data.dt1) console.log(re.data.dt1);//可以直接訪問屬性的,不需要做其他的事情,因為返回的純json是已經解析后的數據,如果是數組或者list,可以直接each,非常方便 if(re.data.dt2) console.log(re.data.dt2); } });

這種方式的注意點:

這種方式對ajax,微信等非常友好,兼容性很好,可以直接互相傳遞對象,容器數組等等,都是標准的文件或者json對象,也是主流的趨勢,兼容多種平台。所以推薦使用。

估計有了這兩種方法基本滿足了。


免責聲明!

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



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