原文地址: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对象,也是主流的趋势,兼容多种平台。所以推荐使用。

估计有了这两种方法基本满足了。

一些简单的Post方式WebApi接收参数和传递参数的方法及总结的更多相关文章

  1. JavaWeb_(Struts2框架)参数传递之接收参数与传递参数

    此系列博文基于同一个项目已上传至github 传送门 JavaWeb_(Struts2框架)Struts创建Action的三种方式 传送门 JavaWeb_(Struts2框架)struts.xml核 ...

  2. Android通过DeepLink方式跳转其他App传递参数

    网上对于安卓DeepLink方式跳转传递参数的例子较少,说的也不客观,实践之后发现还是有一些坑.其实为什么要用DeepLink方式跳转,有些是因为引流的原因,他们希望通过网页就能直接跳转到App的界面 ...

  3. SpringMVC入门(二)—— 参数的传递、Controller方法返回值、json数据交互、异常处理、图片上传、拦截器

    一.参数的传递 1.简单的参数传递 /* @RequestParam用法:入参名字与方法名参数名不一致时使用{ * value:传入的参数名,required:是否必填,defaultValue:默认 ...

  4. 17_Android中Broadcast详解(有序广播,无序广播)最终广播,Bundle传递参数,传递参数的时候指定权限

     1  Broadcast是Android中的四大组件之一,他的用途很大,比如系统的一些广播:电量低.开机.锁屏等一些操作都会发送一个广播. 2  广播被分为两种不同的类型:"普通广播( ...

  5. python 函数参数的传递(参数带星号的说明) 元组传递 字典传递

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  6. python 函数参数的传递(参数带星号的说明)

    python中函数参数的传递是通过赋值来传递的.函数参数的使用又有俩个方面值得注意:1.函数参数是如何定义的 2.在调用函数的过程中参数是如何被解析 先看第一个问题,在python中函数参数的定义主要 ...

  7. SpringMVC中,前台jsp封装参数,绑定参数,传递参数到后台controller的过程详解

    前台到后台的流程:前台jsp->后台:controller控制器层->service业务层->DAO数据访问层->数据库model模型层. 从上面流程可知,前台jsp的数据,想 ...

  8. Angular2入门系列教程5-路由(一)-使用简单的路由并在在路由中传递参数

    上一篇:Angular2入门系列教程-服务 上一篇文章我们将Angular2的数据服务分离出来,学习了Angular2的依赖注入,这篇文章我们将要学习Angualr2的路由 为了编写样式方便,我们这篇 ...

  9. ashx接收参数 ashx传递参数

    原文发布时间为:2009-09-30 -- 来源于本人的百度文章 [由搬家工具导入] Handler.ashx文件: <%@ WebHandler Language="C#" ...

  10. [python] 带有参数并且传递参数的装饰器

    场景时这样的,我有个一大堆任务,我要给这些任务计时,入库.就需要一个带有参数的装饰器来记录任务名称, 在任务执行前和执行之后都需要记录任务当时执行的时刻. #-*- encoding=utf-8 -* ...

随机推荐

  1. 18 JavaScript中的三元运算

    18 JavaScript中的三元运算 先来看一个例子: let a = 10; let b = 20; let d = a > b? a: b console.log(d); // 20 三元 ...

  2. #trie,树链剖分#洛谷 6088 [JSOI2015]字符串树

    题目 分析 显然树上的问题可以转换成根节点到两点的答案减去2倍根节点到LCA的答案 化边为点,考虑子节点承接父节点的trie,再加入一条新的字符串, 在循环的过程中统计一个位置被多少个字符串经过, 这 ...

  3. C 语言中的 switch 语句和 while 循环详解

    C 语言中的 switch 语句 替代多重 if..else 语句,可以使用 switch 语句.switch 语句用于选择多个代码块中的一个来执行 switch(表达式) { case x: // ...

  4. 直播预告丨Hello HarmonyOS进阶课程第三课——游戏开发实践

    为了帮助初识HarmonyOS的开发者快速入门,我们曾推出Hello HarmonyOS系列一共5期课程,从最基础的配置IDE和创建Hello World开始,详细介绍HarmonyOS基础.开发环境 ...

  5. How Python Handles Big Files

     The Python programming language has become more and more popular in handling data analysis and proc ...

  6. 重新点亮shell————周期性脚本[八]

    前言 简单介绍一下周期性脚本 正文 周期性脚本之前先介绍一下信号. 捕获信号脚本的编写: kill 默认会发送15号信号给应用程序 ctrl+c 发送2号信号给应用程序 9号信号不可阻塞信号 所以只有 ...

  7. mysql 在c# EF 中无法生成对象

    正文 1. 创建个vs2013项目,导入EntityFramework.dll. MySql.Data.dll. MySql.Data.Entity.EF6.dll 2. 工具 -> 扩展和更新 ...

  8. node excel采集数据

    前言 个人写过无数的脚本,但是一直没有整理,后续整理脚本. 需求: 生成一堆激活码. 业务: 需要拿到一个token, 然后调用某个api获取激活码. 正文 思路: 1.http请求 axios 2. ...

  9. Chat2table,简易表格分析助手

    一 写在前面 之前用智谱AI的Chatglm3-6b模型写过一个简单的论文阅读助手,可用来辅助论文阅读等.而像表格,如Excel.CSV文件等内容的分析,也是不可忽略的需要,因此本文同样使用Chatg ...

  10. [Violation] 'click' handler took 429ms

    问题 violation 意思为侵权,违背,违反,也就是说明click函数执行违反了某些规则 原因测试 当click事件中执行的程序耗时过长,超过160ms左右的时候就会显示该信息,测试最低155ms ...