基于.Net Framework 4.0 Web API开发(2):ASP.NET Web APIs 参数传递方式详解
概述:
ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作。调用API过程中参数的传递是必须的,本节就来谈谈API使用过程中参数的传递方式。
各种参数传递方式的实现:
ASP.NET Web API参数有两种传递方式,一种是请求时携带QueryString,Action中没有表中标注FromUri和FromBody属性且没有默认值的参数,Request请求时必需一QueryString的方式携带参数?A=&B=&C=1,及时没有值,也得传递,否则报404错误。
API 开发中的FromUriAttribute属性,主要是用来在GET请求中传递复杂对象,并且每个API可以含有多个此类型的参数,但每个复杂对象中的属性名不能相同,否则无法正确传值,除非两个参数的相同属性的属性值相同,不过此种方式传递有一定的局限性,就是url长度限制,变相的限定此种方式的参数数据量的大小。
另外一种传递方式就是请求Request的发送内容携带数据,对应API开发中的FromBodyAttribute属性,此种方式主要应对POST请求参数的传递,可以传递复杂的类型,包括数组,list等,但是每个API有且仅有一个这样的参数,如果有多个,就会报无法将多个参数绑定到请求的内容
不多上,下面上代码,一种一种讲解:
1. 简单类型传递
简单类型包括 int(decimal,long,float)、string(char)、bool、datetime、guid,主要就这几种
模板: public TResult nameOfFunction([FromUrl]int i, [FromUrl]string s, ……)
=> public TResult nameOfFunction(int i, string s, ……)
但模板: public TResult nameOfFunction([FromUrl]ClassA a, [FromUrl]Class b, ……)
≠> public TResult nameOfFunction(ClassA a, ClassB b, ……)
[HttpGet]
public ResultData TestParameter(int i, string s, bool b, DateTime t, Guid g)
{
try
{
var data = new { i = i, s = s, b = b, t = t, g = g};
return new ResultData(data);
}
catch (Exception ex)
{
throw ex;
//return new ResultData(ResultType.SystemException, ex.Message);
}
} //TestParameter
function TestParameter() {
var v = { i: , b: false, t: "2016-07-06", g: "E816F0B7-2FB7-47D9-84ED-119F58C9BEC5", s: "test"};
$.ajax({
type: "get",
url: host + "/mobileapi/test/TestParameter",
dataType: "text",
data: v,
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert("报错无语");
}
});
}
结果如下:

注意:
1. GET 类型请求的API不能含有[FromBody]属性的参数,虽然不会报错,但永远没为null,如果GET请求需要传递复杂参数,可以用FromUri属性修饰参数
2. API参数没有默认值的情况下,请求的参数名称必需与API参数名称保持一致,但不区分大小写,且能对应上的参数个数一定相等,否则会报404错误。
详细列举如下:
a. 参数个数相等,但对应的参数少个 g,所有找不到对应API,报404错误
function TestParameter() {
var v = { i: , b: false, t: "2016-07-06", s: "test", a: "会报404错误" };
$.ajax({
type: "get",
url: host + "/mobileapi/test/TestParameter",
dataType: "text",
data: v,
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert("报错无语");
}
});
}
b. 参数个数不相等,但是能对应上的参数个数相等,不会报404错误
//TestParameter
function TestParameter() {
var v = { i: , b: false, t: "2016-07-06", s: "test", g: "E816F0B7-2FB7-47D9-84ED-119F58C9BEC5", a: "不会报404错误" };
$.ajax({
type: "get",
url: host + "/mobileapi/test/TestParameter",
dataType: "text",
data: v,
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert("报错无语");
}
});
}
如何调整使上述几种方式也能找到正确的API的呢?这就需要.NET Framework的默认参数功能,API的调整如下:
[HttpGet]
public ResultData TestParameter(int i, string s, bool b, DateTime t, Guid? g = null)
{
try
{
var data = new { i = i, s = s, b = b, t = t, g = g };
return new ResultData(data);
}
catch (Exception ex)
{
throw ex;
//return new ResultData(ResultType.SystemException, ex.Message);
}
}
以上代码最后一个参数g有个默认值null,这样get请求的时候可以没有g参数也能请求通过,不会报404错误。另外,值类型的参数最好定义为nullable形式(简写可以?标注),这样的参数赋值不正确的时候也不会报异常错误,只是参数值为null。特别是日期类,如果不是nullable类型,不传值和传错值都会报异常
上面例子中的t参数如果为 TestParameter?i=1&b=false&t=2016-37-06&s=test&g=E816F0B7-2FB7-47D9-84ED-119F58C9BEC5或者
http://192.168.1.135:1507/mobileapi/test/TestParameter?i=1&b=false&t=&s=test&g=E816F0B7-2FB7-47D9-84ED-119F58C9BEC5,都会报错,如果定义为nullable类型就一切正常: public ResultData TestParameter(int i, string s, bool b, DateTime? t, Guid? g = null)。
2. 复杂类型传递
GET请求中复杂类型的传递需要FormUriAttribute属性配合,并且每个API可以有多个FromUri标示的参数,也可以在post请求中使用此属性标注的参数。
1 [HttpGet]
2 public ResultData TestParameter2([FromUri]List<int> ids, [FromUri]User a)
3 {
4 try
5 {
6 var data = new { ids=ids, name=a.name };
7 return new ResultData(data);
8 }
9 catch (Exception ex)
10 {
11 throw ex;
12 //return new ResultData(ResultType.SystemException, ex.Message);
13 }
14 }
测试代码:
1 function TestParameter2() {
2 var v = { ids: [1, 2, 3], name='test', age=4, weight=100 };
3 $.ajax({
4 type: "get",
5 url: host + "/mobileapi/test/TestParameter2",
6 dataType: "text",
7 data: { "": v },
8 beforeSend: function (request) {
9 request.setRequestHeader("token", $("#token").val());
10 },
11 success: function (data) {
12 alert(data);
13 },
14 error: function (x, y, z) {
15 alert("报错无语");
16 }
17 });
18 }
测试结果:GET请求中可以利用FromUri属性传递复杂类型
POST请求中复杂类型的传递需要FormBodyAttribute属性配合,并且每个API有且仅有一个FromBody标示的参数,并且只能在post请求中使用。
[HttpPost]
public ResultData TestParameter2([FromBody]List<int> ids, [FromBody]List<int> ids2)
{
try
{
var data = new { ids=ids, ids2=ids2 };
return new ResultData(data);
}
catch (Exception ex)
{
throw ex;
//return new ResultData(ResultType.SystemException, ex.Message);
}
}
[HttpPost]
public ResultData TestParameter2([FromBody]List<int> ids, [FromBody]ProductData pd)
{
try
{
var data = new { ids = ids, pd = pd };
return new ResultData(data);
}
catch (Exception ex)
{
throw ex;
//return new ResultData(ResultType.SystemException, ex.Message);
}
}
以上两个示例中代码编译不报错,可以正常编译,但是请求会报错,报错信息如下:
测试代码:
function TestParameter2() {
var v = { ids: [, , ], ids2: [, , ] };
$.ajax({
type: "post",
url: host + "/mobileapi/test/TestParameter2",
dataType: "text",
data: { "": v },
beforeSend: function (request) {
request.setRequestHeader("token", $("#token").val());
},
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert("报错无语");
}
});
}
function TestParameter2() {
var v = { "ids": [, , ], pd: { barcode: "ddddd" } };
$.ajax({
type: "post",
url: host + "/mobileapi/test/TestParameter2",
dataType: "text",
data: { "": v },
beforeSend: function (request) {
request.setRequestHeader("token", $("#token").val());
},
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert("报错无语");
}
});
}
测试结果:
以上两组测试都会报无法将多个参数绑定到请求的内容异常
3. 数组参数的正确传递
调整一下API,只接收一个FromBody参数,并为List<int>
[HttpPost]
public ResultData TestParameter2([FromBody]List<int> ids)
{
try
{
var data = new { ids = ids, pd = pd };
return new ResultData(data);
}
catch (Exception ex)
{
throw ex;
//return new ResultData(ResultType.SystemException, ex.Message);
}
}
测试一:
//TestParameter
function TestParameter2() {
var v = { "ids": [, , ] };
$.ajax({
type: "post",
url: host + "/mobileapi/test/TestParameter2",
dataType: "text",
data: { "": v },
beforeSend: function (request) {
request.setRequestHeader("token", $("#token").val());
},
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert("报错无语");
}
});
}
测试一的结果:
测试二:
//TestParameter
function TestParameter2() {
var v = { "": [, , ] };
$.ajax({
type: "post",
url: host + "/mobileapi/test/TestParameter2",
dataType: "text",
data: { "": v },
beforeSend: function (request) {
request.setRequestHeader("token", $("#token").val());
},
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert("报错无语");
}
});
}
测试二结果:
分析: 经过测试一和测试二结果观察,数据传递格式不能数组名,其实这个不是数组传递的问题,而是WEB API frombody参数的一种约定,所以每个API只能有一个frombody格式的参数,因为这样的参数不会依据属性名对应解析,而是把body中发送的所有数据解析成一个对象,所以无法定义多个 frombody 格式参数。
结论: 经过frombody修饰的参数只能有一个,并且经过frombody修饰的参数无论是简单类型,还是复杂类型(包括数组,list,系统class和自定义class等),传参都不需要属性名,属性名必需为空字符串(“”),否则无法解析,参数永远为null
参数格式的列举:
简单类型json参数格式: {"":1} 、{"":1.0} 、{"":"test"} 、{"":"C"} 、{"":"2016-03-10"} 、{"":"BC069BF1-1382-4C5D-B3B1-9643F3F94A9D"}
类定义如下:
public class User
{
public string Name { get; set; }
public int Age { get; set; }
public DateTime? Birthday { get; set; }
} 类类型json参数格式:{name:"Tom", age:18, birthday:"2016-03-10"}
4. FromUrl参数和FromBody参数混合使用,这种混合使用规则参照以上使用方法,没难度。
[HttpPost]
public ResultData TestParameter2(int i, string s, [FromUri]bool b, DateTime? t, Guid? g = null, [FromBody]List<int> ids = null)
{
try
{
var data = new { ids = ids };
return new ResultData(data);
}
catch (Exception ex)
{
throw ex;
//return new ResultData(ResultType.SystemException, ex.Message);
}
}
此篇到此结束,欢迎大家讨论!
补充:API中Action参数传递方式总结说明
1. 参数不带任何属性标签 Action F1(string a, string b)
querystring中必需含有 a和b查询字符串 url?a=1&b=, 即使b没有值,也必需携带,否则报404错误,找不到符合请求的Action
2. 参数带有fromuri属性 Action F2(string a, [FromUri]stirng b)
querystring中必需含有 a查询字符串,b可以不带,因为被属性[FromUri]修饰,例: url?a=1&b=或url?a=1都能匹配到F2 action, b没有值可以不携带,但参数a必需携带
3. 带有fromuri属性的参数可以有多个 Action F3(string a, [FromUri]stirng b,[FromUri]stirng c,[FromUri]stirng d) ,
请求方法同2, 例如: url?a=1&b=2&d=3
4. 带有frombody属性的参数只适应post请求,否则永远为null ,并且可以与fromuri混合使用,但每个action,frombody属性参数有且仅有一个,多个会报错
Action F4(string a, [FromUri]stirng b,[FromUri]stirng c,[FromBody]stirng d)
使用方法同 2, 3
这样混合使用不报错,也能正常运行,但需要混合使用的环境比较少,基本上95% Action只用fromuri或frombody就能完成,没必要混合使用
基于.Net Framework 4.0 Web API开发(2):ASP.NET Web APIs 参数传递方式详解的更多相关文章
- ASP.NET Web API 框架研究 ASP.NET Web API 路由
ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...
- web api :Routing in ASP.NET Web API
引 Web API 和SignalR都是在服务层. If you are familiar with ASP.NET MVC, Web API routing is very similar to M ...
- C#自制Web 服务器开发:mysql免安装版配置步骤详解分享
mysql免安装版配置步骤详解分享 1.准备工作 下载mysql的最新免安装版本mysql-noinstall-5.1.53-win32.zip,解压缩到相关目录,如:d:\ mysql-noinst ...
- Java 函数参数传递方式详解 分类: Java Game 2014-08-15 06:34 82人阅读 评论(0) 收藏
转:http://zzproc.iteye.com/blog/1328591 在阅读本文之前,根据自己的经验和理解,大家可以先思考并选择一下Java函数的参数传递方式: A. 是按值传递的? B. ...
- 水果项目第3集-asp.net web api开发入门
app后台开发,可以用asp.net webservice技术. 也有一种重量级一点的叫WCF,也可以用来做app后台开发. 现在可以用asp.net web api来开发app后台. Asp.net ...
- Asp.Net Web API 2第五课——Web API路由
Asp.Net Web API 导航 Asp.Net Web API第一课——入门 http://www.cnblogs.com/aehyok/p/3432158.html Asp.Net Web ...
- Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 Part 3 (by TAISEER)
http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-an ...
- 循序渐进学.Net Core Web Api开发系列【0】:序言与目录
一.序言 我大约在2003年时候开始接触到.NET,最初在.NET framework 1.1版本下写过代码,曾经做过WinForm和ASP.NET开发.大约在2010年的时候转型JAVA环境,这么多 ...
- ASP.NET Core Web API 开发-RESTful API实现
ASP.NET Core Web API 开发-RESTful API实现 REST 介绍: 符合REST设计风格的Web API称为RESTful API. 具象状态传输(英文:Representa ...
随机推荐
- 纯CSS实现3D按钮效果
今天分享一个用纯CSS实现的3D按钮.css巧妙利用了box-shadow来实现3D物体的立体感,当按钮按下的时候再去修改box-shadow和top值.让人感觉有一种按钮被按下的感觉.css代码非常 ...
- Android开发学习之路-GSON使用心得(OCR图片识别)
在安卓中解析JSON串可以使用的方法有很多,比如说用官方提供的JSONObject或者谷歌提供的开源库GSON,以及一些第三方开源库. 这里用的是GSON,为了测试方便,借助了一个百度的api,一个图 ...
- salesforce 零基础开发入门学习(九)Approval Process 介绍
在阅读此篇文章前,可以先参考阅读一个前辈总结的关于Approval Process的操作.以下为参考的链接: http://www.cnblogs.com/mingmingruyuedlut/p/37 ...
- Win7系统.net framework 4.0没有注册导致部署在IIS的站点跑不起来怎么办
win7装了VS再装IIS,结果IIS里面有.NET4.0,但是程序始终是跑不起来,怎么办呢? 分析觉得可能是因为4.0没有注册到IIS,在win7下如果先安装vs2010 (附带会安装Microso ...
- DOM_04之常用对象及BOM
1.添加:①var a=document.createElement("a"):②设置关键属性:③将元素添加到DOM树:a.parent.appendChild(a):b.pare ...
- 使用swoole和websocket结合来制造弹幕
在知乎上无意中看到了一篇有关这个的话题https://zhuanlan.zhihu.com/p/23992890,刚好没事也好久没弄swoole了就自己按照知乎上的那篇文站实操了一下 那个试验中有几个 ...
- 那些年我们写过的T-SQL(中篇)
中篇的重点在于,在复杂情况下使用表表达式的查询,尤其是公用表表达式(CTE),也就是非常方便的WITH AS XXX的应用,在SQL代码,这种方式至少可以提高一倍的工作效率.此外开窗函数ROW_NUM ...
- ASP.NET将Session保存到数据库中
因为ASP.NET中Session的存取机制与ASP相同,都是保存在进行中, 一旦进程崩溃,所有Session信息将会丢失,所以我采取了将Session信息保存到SQL Server中,尽管还有其它的 ...
- Spring学习总结(六)——Spring整合MyBatis完整示例
为了梳理前面学习的内容<Spring整合MyBatis(Maven+MySQL)一>与<Spring整合MyBatis(Maven+MySQL)二>,做一个完整的示例完成一个简 ...
- Sparse Filtering 学习笔记(三)目标函数的建立和求解
Sparse Filtering 是一个用于提取特征的无监督学习算法,与通常特征学习算法试图建模训练数据的分布的做法不同,Sparse Filtering 直接对训练数据的特征分布进行分析,在所谓 ...