Web API(四):Web API参数绑定

在这篇文章中,我们将学习Web API如何将HTTP请求数据绑定到一个操作方法的参数中。

操作方法在Web API控制器中可以有一个或多个不同类型的参数。它可以是基本数据类型或复杂类型。Web API根据URL的查询字符串或请求主体中参数类型来绑定操作方法的参数。

如果参数类型是基本数据类型(int,double,string,DateTime,bool等),Web API默认将会从URL中获取参数值(即通过query string)获取。

如果参数类型的复杂类型,Web API默认从请求主体中获取参数值。

下表列出了Web API参数绑定的默认规则。

HTTP方法 Query String Request Body
GET 简单类型 不能从请求主体中获取参数值
POST 简单类型 复杂类型
PUT 简单类型 复杂类型
PATCH 简单类型 复杂类型
DELETE 简单类型 不能从请求主体中获取参数值

我们先来看看创建带MVC的Web API项目时自动生成的Values控制器是如何定义的。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Net;
 5 using System.Net.Http;
 6 using System.Web.Http;
 7 
 8 namespace WebAPIContainMVC.Controllers
 9 {
10     public class ValuesController : ApiController
11     {
12         // GET api/values
13         public IEnumerable<string> Get()
14         {
15             return new string[] { "value1", "value2" };
16         }
17 
18         // GET api/values/5
19         public string Get(int id)
20         {
21             return "value";
22         }
23 
24         // POST api/values
25         public void Post([FromBody]string value)
26         {
27         }
28 
29         // PUT api/values/5
30         public void Put(int id, [FromBody]string value)
31         {
32         }
33 
34         // DELETE api/values/5
35         public void Delete(int id)
36         {
37         }
38     }
39 }

从Values控制器的定义中,我们可以得出如下几个结论:

(1)Web API常规的方法有四个:Get(),Post(),Put()和Delete()。

(2)四种方法的参数可以归纳为两大类:URL传递(Request-url)和Body(Request-body)传递。

(3)可以将四种方法的参数传递归为两大类,而这两大类又集中在Get和Post中体现(Put是Get和Post的组合,Delete和Get类型),所以说研究Web API的参数绑定,只需要研究Get和Post方法的参数传递即可,Get对应Request-url,Post对应Request-Body。

在本篇文章中,客户端调用使用Fiddler工具进行测试。

一、Get

1、基本数据类型作为方法参数

1.1 方法只含有一个参数(形参可以传递进来)

方法定义如下:

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Net;
 5 using System.Net.Http;
 6 using System.Web.Http;
 7 using WebAPIContainMVC.Entity;
 8 
 9 namespace WebAPIContainMVC.Controllers
10 {
11     public class StudentController : ApiController
12     {
13         [HttpGet]
14         public string GetStudentById(int id)
15         {
16             string strResult=string.Empty;
17             List<Student> list = new List<Student>();
18             Student stu = new Student() 
19             {
20               StudentId=1,
21               Name="Tom",
22               Age=20,
23               Sex=""
24             };
25             list.Add(stu);
26             list.ForEach(p => 
27             {
28                 if (p.StudentId.Equals(id))
29                 {
30                     strResult = "存在该学生信息";
31                 }
32                 else
33                 {
34                     strResult = "对不起,找不到该学生信息";
35                 }
36             });
37 
38         return strResult;
39         }
40     }
41 }

 客户端调用

结果:

双击左侧的进程,得到如下的结果

1.2、方法含有多个参数(形参可以传递进来)

方法定义如下:

public string GetStudentByIdAndName(int id,string name)
{
            string strResult = string.Empty;
            List<Student> list = new List<Student>();
            Student stu = new Student()
            {
                StudentId = 1,
                Name = "Tom",
                Age = 20,
                Sex = "男"
            };
            list.Add(stu);
            list.ForEach(p =>
            {
                if (p.StudentId.Equals(id)&&p.Name.Equals(name))
                {
                    strResult = "存在该学生信息";
                }
                else
                {
                    strResult = "对不起,找不到该学生信息";
                }
            });

            return strResult;
}

URL地址:http://localhost:63512/api/student?id=1&&name=Tom

结果如下:

2、实体对象类型作为方法参数(形参不能传递进来)

方法定义如下:

[HttpGet]
public string GetStudent(Student student)
{
            string strResult = string.Empty;
            List<Student> list = new List<Student>();
            Student stu = new Student()
            {
                StudentId = 1,
                Name = "Tom",
                Age = 20,
                Sex = "男"
            };
            list.Add(stu);
            if (student != null)
            {
                list.ForEach(p =>
                {
                    if (p.StudentId.Equals(student.StudentId))
                    {
                        strResult = "存在该学生信息";
                    }
                    else
                    {
                        strResult = "对不起,找不到该学生信息";
                    }
                });
            }
            else
            {
                strResult = "参数值为Null";
            }
     

            return strResult;
}

客户端调用结果如下:

3、基本数据类型和实体对象混合作为方法参数(基本数据类型可以传递进来,实体对象不能传递进来)

4、总结

(1)查询字符串参数名称和操作方法参数名称必须相同(不区分大小写)。参数的先后顺序可以不一致。

(2)Get()参数传递的本质是URL字符串拼接,但是URL字符串的长度受限制。

(3)Get()的参数支持基本数据类型,不支持实体数据类型。

(4)Get()参数的传递是在Http请求的头部传递,而不支持Request-Body传递。

(5)Get类型的方法命名,尽量采用“Get+方法名”的命名方式,在方法前面加上特性:[HttpGet]。

二、Post

1、Post参数传递是在Request-Body内传递。

2、Post参数可以传递基本数据类型,也可以传递实体数据类型。

3、Post操作方法只能包含一个实体数据类型,因为只能允许一个参数读取Request-Body中的数据。

4、Post传递参数时,无论是基本类型参数还是实体类型,均需要借助[FromBody]特性。(有些情况下不写[FromBody]特性也可以把参数传递进来,但为了规范化,最好是加上该特性)。

5、Post类型的方法命名,尽量采用“Post+方法名”的命名方式,在方法前面加上特性:[HttpPost]。

三、FromURI与FromBody

在默认情况下,Web API是从查询字符串中得到基本数据类型参数的值,从请求主体中得到复杂类型参数的值,如果想改变这种默认情况怎么办?

可以使用[FromURI]属性,是Web API从查询字符串中获取复杂类型参数的值,使用[FromBody]属性可以使Web API从请求主体中获取基本数据类型参数的值。

例如下面的Get方法

[HttpGet]
public string GetStudentById([FromUri]Student stu)
{ 
        
}

Get方法中包括复杂的类型参数,参数添加了[FromUri]属性,Web API将试图从查询字符串中得到Student类型参数的值。

同样,参考下面的Post方法:

[HttpPost]
public string Post([FromBody]string name)
{ }

 Web API将从请求主体中获取基本类型参数的值,而不是从请求字符串中获取。

原文地址:https://www.cnblogs.com/dotnet261010/p/8592067.html