基于.Net Framework 4.0 Web API开发(2):ASP.NET Web APIs 参数传递方式详解

概述: 

  ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作。调用API过程中参数的传递是必须的,本节就来谈谈API使用过程中参数的传递方式。

各种参数传递方式的实现:

ASP.NET Web API参数有两种传递方式,一种是请求时携带QueryString,对应API 开发中的FromUrlAttribute属性,也是参数传递默认属性,并且每个API可以含有多个此类型的参数,主要应对GET请求,但此种方式传递有一定的局限性,比如复杂类型的参数,此种传递方式就不能胜任,就像常用的数组参数也不能用此种方式传递,还有就是url长度限制,变相的限定此种方式的参数数据量的大小。

另外一种传递方式就是请求Request的发送内容携带数据,对应API开发中的FromBodyAttribute属性,此种方式可以传递复杂的类型,包括数组,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, ……)

 1         [HttpGet]
 2         public ResultData TestParameter(int i, string s, bool b, DateTime t, Guid g)
 3         {
 4             try
 5             {
 6                 var data = new { i = i, s = s, b = b, t = t, g = g};
 7                 return new ResultData(data);
 8             }
 9             catch (Exception ex)
10             {
11                 throw ex;
12                 //return new ResultData(ResultType.SystemException, ex.Message);
13             }
14         }
15
16         //TestParameter
17 function TestParameter() {
18     var v = { i: 1, b: false, t: "2016-07-06", g: "E816F0B7-2FB7-47D9-84ED-119F58C9BEC5", s: "test"};
19     $.ajax({
20         type: "get",
21         url: host + "/mobileapi/test/TestParameter",
22         dataType: "text",
23         data: v,
24         success: function (data) {
25             alert(data);
26         },
27         error: function (x, y, z) {
28             alert("报错无语");
29         }
30     });
31 }

结果如下:

注意:

 1. GET 类型请求的API不能含有[FromBody]属性的参数,虽然不会报错,但永远没为null

 2. API参数没有默认值的情况下,请求的参数名称必需与API参数名称保持一致,但不区分大小写,且能对应上的参数个数一定相等,否则会报404错误。

详细列举如下:

a. 参数个数相等,但对应的参数少个 g,所有找不到对应API,报404错误

 1 function TestParameter() {
 2     var v = { i: 1, b: false, t: "2016-07-06", s: "test", a: "会报404错误" };
 3     $.ajax({
 4         type: "get",
 5         url: host + "/mobileapi/test/TestParameter",
 6         dataType: "text",
 7         data: v,
 8         success: function (data) {
 9             alert(data);
10         },
11         error: function (x, y, z) {
12             alert("报错无语");
13         }
14     });
15 }

b. 参数个数不相等,但是能对应上的参数个数相等,不会报404错误

 1 //TestParameter
 2 function TestParameter() {
 3     var v = { i: 1, b: false, t: "2016-07-06", s: "test", g: "E816F0B7-2FB7-47D9-84ED-119F58C9BEC5", a: "不会报404错误" };
 4     $.ajax({
 5         type: "get",
 6         url: host + "/mobileapi/test/TestParameter",
 7         dataType: "text",
 8         data: v,
 9         success: function (data) {
10             alert(data);
11         },
12         error: function (x, y, z) {
13             alert("报错无语");
14         }
15     });
16 }

如何调整使上述几种方式也能找到正确的API的呢?这就需要.NET Framework的默认参数功能,API的调整如下:

 1  [HttpGet]
 2         public ResultData TestParameter(int i, string s, bool b, DateTime t, Guid? g = null)
 3         {
 4             try
 5             {
 6                 var data = new { i = i, s = s, b = b, t = t, g = g };
 7                 return new ResultData(data);
 8             }
 9             catch (Exception ex)
10             {
11                 throw ex;
12                 //return new ResultData(ResultType.SystemException, ex.Message);
13             }
14         }

以上代码最后一个参数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. 复杂类型传递

复杂类型的传递需要FormBodyAttribute属性配合,并且每个API有且仅有一个FromBody标示的参数,并且只能在post请求中使用。

 1  [HttpPost]
 2         public ResultData TestParameter2([FromBody]List<int> ids, [FromBody]List<int> ids2)
 3         {
 4             try
 5             {
 6                 var data = new { ids=ids, ids2=ids2 };
 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         [HttpPost]
 2         public ResultData TestParameter2([FromBody]List<int> ids, [FromBody]ProductData pd)
 3         {
 4             try
 5             {
 6                 var data = new { ids = ids, pd = pd };
 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], ids2: [4, 5, 6] };
 3     $.ajax({
 4         type: "post",
 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 }
 1 function TestParameter2() {
 2     var v = { "ids": [1, 2, 3], pd: { barcode: "ddddd" } };
 3     $.ajax({
 4         type: "post",
 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 }

测试结果:

以上两组测试都会报无法将多个参数绑定到请求的内容异常

3. 数组参数的正确传递

调整一下API,只接收一个FromBody参数,并为List<int>

 1         [HttpPost]
 2         public ResultData TestParameter2([FromBody]List<int> ids)
 3         {
 4             try
 5             {
 6                 var data = new { ids = ids, pd = pd };
 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 //TestParameter
 2 function TestParameter2() {
 3     var v = { "ids": [1, 2, 3] };
 4     $.ajax({
 5         type: "post",
 6         url: host + "/mobileapi/test/TestParameter2",
 7         dataType: "text",
 8         data: { "": v },
 9         beforeSend: function (request) {
10             request.setRequestHeader("token", $("#token").val());
11         },
12         success: function (data) {
13             alert(data);
14         },
15         error: function (x, y, z) {
16             alert("报错无语");
17         }
18     });
19 }

测试一的结果:

测试二:

 1 //TestParameter
 2 function TestParameter2() {
 3     var v = { "": [1, 2, 3] };
 4     $.ajax({
 5         type: "post",
 6         url: host + "/mobileapi/test/TestParameter2",
 7         dataType: "text",
 8         data: { "": v },
 9         beforeSend: function (request) {
10             request.setRequestHeader("token", $("#token").val());
11         },
12         success: function (data) {
13             alert(data);
14         },
15         error: function (x, y, z) {
16             alert("报错无语");
17         }
18     });
19 }

测试二结果:

分析: 经过测试一和测试二结果观察,数据传递格式不能数组名,其实这个不是数组传递的问题,而是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"}

类定义如下:

1     public class User
2     {
3         public string Name { get; set; }
4         public int Age { get; set; }
5         public DateTime? Birthday { get; set; }
6     }

类类型json参数格式:{name:"Tom", age:18, birthday:"2016-03-10"}

4. FromUrl参数和FromBody参数混合使用,这种混合使用规则参照以上使用方法,没难度。

 1         [HttpPost]
 2         public ResultData TestParameter2(int i, string s, bool b, DateTime? t, Guid? g = null, [FromBody]List<int> ids = null)
 3         {
 4             try
 5             {
 6                 var data = new { ids = ids };
 7                 return new ResultData(data);
 8             }
 9             catch (Exception ex)
10             {
11                 throw ex;
12                 //return new ResultData(ResultType.SystemException, ex.Message);
13             }
14         }

此篇到此结束,欢迎大家讨论!

时间: 07-08

基于.Net Framework 4.0 Web API开发(2):ASP.NET Web APIs 参数传递方式详解的相关文章

水果项目第3集-asp.net web api开发入门

app后台开发,可以用asp.net webservice技术. 也有一种重量级一点的叫WCF,也可以用来做app后台开发. 现在可以用asp.net web api来开发app后台. Asp.net web api 官方定义: ASP.NET Web API is a framework that makes it easy to build HTTP services that reach a broad range of clients, including browsers and mo

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 API第二课——CRUD操作 http://www.cnblogs.com/aehyok/p/3434578.html Asp.Net Web API第三课——.NET客户端调用Web API http://www.cnblogs.com/aehyok/p/3439698.html Asp.Net

Implement JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1

http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/ Currently our API doesn’t support authentication and authorization, all the requests we receive to any end point are done anonymously, I

循序渐进学.Net Core Web Api开发系列【9】:常用的数据库操作

系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇描述一些常用的数据库操作,包括:条件查询.排序.分页.事务等基本数据库操作.试验的数据库为MySQL. 二.条件查询1.查询所有记录 List<Article> articles = _context.Articles.ToList<Article>(); 2.根据主键进行查询 Articl

Asp.Net Web API开发微信后台

如果说用Asp.Net开发微信后台是非主流,那么Asp.Net Web API的微信后台绝对是不走寻常路. 需要说明的是,本人认为Asp.Net Web API在开发很多不同的请求方法的Restful服务的时候是利器,可在开发微信后台的时候,因为微信调用我们这个后台的时候来来去去就一个方法,所以Web API有点杀鸡用牛刀的感觉. 而且由于Web API其实是微软封装了大量的类库,所以会导致后台相当臃肿.所以,不建议Asp.Net Web API开发微信后台. 如果好奇心太强实在想试一下,可以参

使用GraceNote Web API开发Mac查询音乐信息应用

好久没写博客了,最近各种忙,大忙特忙,今晚难得有空,写个博客总结下最近完成的一个任务:使用GraceNote的Web API来开发一个查询音乐信息的应用,其实功能和前面的那些GraceNote SDK的博文是一样的,只是这一次不使用任何SDK,单纯的使用Web API,然后开发的平台从iOS转移到了Mac上,于是,我人生中第一个Mac App Demo就出来了. GraceNote Web API的官方资料:点击打开链接 首先看下基本的查询和响应的数据格式: 可以看到交互的形式是XML. 事实上

循序渐进学.Net Core Web Api开发系列【8】:访问数据库(基本功能)

系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇讨论如何连接数据库,包括连接SQL Server 和 连接MySQL,然后做一些基本的数据操作. 二.连接SQL Server 首先通过NuGet添加相关的包: 新建一个实体类: public class Product { [Key] public string Code { get; set; } p

循序渐进学.Net Core Web Api开发系列【13】:中间件(Middleware)

系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 本篇介绍如何使用中间件(Middleware). 二.初步演练 先写几个中间件 public class DemoAMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; public Dem

循序渐进学.Net Core Web Api开发系列【1】:开发环境

系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.本篇概述 本篇不打算描述如何通过Visual Studio创建一个项目之类的话题,主要描述以下内容: 1.使用NuGet和Bower引入第三方库 2.Linux下安装运行环境 3.关于安装虚拟机时碰到的网络设置的问题 实验环境:Windows 10 ,Visual Studio 2017 ,VM 14 , Cent