一些简单的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;
}
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();
var url = "http://XXX/api/XX?p1=param1"
var p2 = "param2"
$.post(url, "="+p2, function(res){
alert(res);
});
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);
}
});
第二种:
[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) > 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对象,也是主流的趋势,兼容多种平台。所以推荐使用。
估计有了这两种方法基本满足了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异