webapi2:给前端提供数据的框架
Restful(语义)的数据提供方式:
Get(查)从服务器获取
Post(增)发送到服务器
Put(改)修改
Delete(删)删除
- MVC控制器:Controller
- API控制器:ApiController
返回值类型自动识别处理,可以返回对象和对象数组,列出成员
WebApiConfig.cs设置api的路由:
- 路由name不能重复
- routeTemplate不加api前缀会与MVC路由冲突
- 没有默认值:api是用来传输数据的,没有默认数据一说
Restful(语义)方式传输数据,action方法需要带对应的关键字(get、post等),例如GetAddress()可以,Address()不行
简单数据(id,name等)可以用url传参,post、put提交对象数据需要data提交
非Restful风格:
-
路由前缀[RoutePrefix("(控制器路径)")]为控制器下的每个方法添加一个内容为控制器路径的前缀
-
需要自己指定处理类型,例[HttpPost] 手动定义路由名[Route("(方法路由名)")]
-
完整示例:
[RoutePrefix("控制器路径")]
控制器:ApiController
{
[HttpPost]//还有[HttpGet]等特性,注明此action只能通过POST方法调用
[Route("方法路由名")]
行为方法(类型 参数)
{...}
}
- 方法路由名与方法名不一定一致,以路由名为主
- 行为方法的参数类型前可以加上[FromBody]限制,如:行为方法([FromBody]类型 参数)
[FromBody]
注明参数只能从Post请求体(body)中获取,FromBodyAttribute强制要求被其修饰的参数,必须是序列化后的实体成员。[FromBody]在一个方法中只能修饰一个参数。
- 如果客户端Content-Type是application/json, api接口如果是用单个对象做参数的时候,加或者不加[FromBody]都可以正常解析参数,但是接口是用对象列表做参数时候,则必须加[FromBody],否则读取不到参数。
- 如果客户端Content-Type不是application/json,api接口必须加[FromForm],否则客户端调用接口会报400错误。
- 如果加上[FromBody],客户端Content-Type不是application/json,接口会报400错误。
WebAPI请求
对于前端页面发起的get/post请求作出相应的处理,前端使用JQuery发起异步请求实现数据调用
一、Get请求
通过url传参
1. 无参数的Get请求
一般的 get 请求我们可以使用 jquery 提供的 $.get() 或者 $.ajax({type:“get”}) 来实现,在url中是拼接在url最后的以?开始的部分
后台方法示例:
public 返回值类型 GetAction(){...}
返回值类型可以是基本数据类型,也可以是类、List集合等等
2. 传递一个参数的Get请求
通常我们需要传递参数只需要指定 ajax 方法的 data 属性即可: data:{“name”:“赵大宝”}
后台方法示例:
public 返回值类型 GetAction(string name){...}
3. 传递多个参数的Get请求
按照上面的方法,对于多个参数我们可以很容易就写出来: data:{“name”:“赵大宝”,“age”:12}
后台方法示例:
public 返回值类型 GetAction(string name,string age){...}
二、Post请求
通过RequestBody传参
1. 无参数的Post请求
我们可以使用 $.post() 或 $.ajax({type:“post”}) 来发起 post 请求
后台方法示例:
public 返回值类型 PostAction(){...}
2. 传递一个参数的 Post 请求
前端data不用key=value而是=value。将key设置为空,如data:{""="赵大宝"}
;或者传一个单纯的字符串由后台去解析,如data:'"name=张三,age=21"'
用单引号包一个双引号,双引号里为字符串内容
后台方法示例:
public 返回值类型 PostAction([FromBody] string name){...}
3. 传递多个参数的Post请求
三种方法
前端:
$.ajax({
url: "/api/student/poststudent",
type: 'POST',
data:JSON.stringify({ name: "张三", age: 21 }),//Json序列化一个对象,小括号中是一个对象,可以单独定义
success:function () {
},
dataType: "json",
contentType: "application/json"
});
- 通过传递一个实体类对象
后端:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
}
[HttpPost]
public 类型 PostStudent(Student student)
{
//student.Age=21
//student.Name="张三"
...
}
- 通过dynamic动态类型
后端:
[HttpPost]
public 类型 PostStudent(dynamic student)
{
var name = student.name;//name大小写与前端参数一致,var类型接收
var age = student.age;
...
}
- JObject参数
后端:
[HttpPost]
public 类型 PostStudent(JObject student)
{
var name = student["name"];
var age = student["age"];
...
}
总结
Get请求与Post请求(以及其他请求方式)的根本原因是http协议以及浏览器规范对http请求传参的规定,从而体现出许多差异。.net WebApi的路由机制是通过模式匹配来进行的,可以自己定义一些路由模板或者启用特性路由,体现了该路由机制的灵活性
相关知识点
- .net WebApi路由机制
- .net WebApi模型绑定
- .net WebApi参数传递
- JQuery/Ajax发起请求
- Json
.net WebAPI2的返回值
- void:返回空的204
- HttpResponseMessage:直接转换为Http相应消息
- IHttpActionResult:调用ExcuteAsync创建HttpResponseMessage,然后将其转换为Http响应消息
- 其他类型:将序列化的返回值写入响应正文返回200
1· void
返回空的HTTP响应,状态码204(无内容)
//控制器
public class ValuesController : ApiController
{
public void Post()
{
}
}
//HTTP响应(控制台)
HTTP/1.1 204 No Content
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 02:13:26 GMT
2· HttpResponseMessage
将返回值直接转换为HTTP响应消息,并使用HttpResponseMessage对象的属性来填充响应,提供了对响应消息的自定义修改操作
//控制器操作设置缓存控制标头
public class ValuesController : ApiController
{
public HttpResponseMessage Get()
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, "value");
response.Content = new StringContent("hello", Encoding.Unicode);
response.Headers.CacheControl = new CacheControlHeaderValue()
{
MaxAge = TimeSpan.FromMinutes(20)
};
return response;
}
}
//响应
HTTP/1.1 200 OK
Cache-Control: max-age=1200
Content-Length: 10
Content-Type: text/plain; charset=utf-16
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 08:53:35 GMT
hello
//如果向CreateResponse方法传递域模型,Web API 将使用媒体格式化程序将序列化模型写入响应正文,使用请求中的 Accept 标头来选择格式化程序
public HttpResponseMessage Get()
{
// Get a list of products from a database.
IEnumerable<Product> products = GetProductsFromDB();
// Write the list to the response body.
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, products);
return response;
}
3· IHttpActionResult 建议使用
- IHttpActionResult是HttpResponseMessage的工厂类,它的优点:
- 简化控制器的单元测试
- 将用于创建Http响应的公共逻辑移到单独的类中
- 通过隐藏构造响应的低级别细节,使控制器操作的意图更清晰
- IHttpActionResult包含单一方法ExecuteAsync,它以异步方式创建HttpResponseMessage实例。如果控制器操作返回IHttpActionResult,Web API 将调用ExecuteAsync方法来创建HttpResponseMessage。然后,将HttpResponseMessage转换为 HTTP 响应消息。
public interface IHttpActionResult
{
Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken);
}
//创建纯文本相应的IHttpActionResult
public class TextResult : IHttpActionResult
{
string _value;
HttpRequestMessage _request;
public TextResult(string value, HttpRequestMessage request)
{
_value = value;
_request = request;
}
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
var response = new HttpResponseMessage()
{
Content = new StringContent(_value),
RequestMessage = _request
};
return Task.FromResult(response);
}
}
//控制器
public class ValuesController : ApiController
{
public IHttpActionResult Get()
{
return new TextResult("hello", Request);
}
}
//响应
HTTP/1.1 200 OK
Content-Length: 5
Content-Type: text/plain; charset=utf-8
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 08:53:35 GMT
hello
- IHttpActionResult是WebAPI中推荐的标准返回值,ApiController类中也提供了几种标准的工厂函数方便我们快速构建它们。
- Json(T content)
- Ok()、 Ok(T content)
- NotFound()
1. Json(T content)
namespace cms.Web.API
{
public class CeshiController : ApiController
{
public studentBLL bll = new studentBLL();
public IHttpActionResult GetList()
{
var list = bll.FindList();
return Json(list);
}
public IHttpActionResult GetList2()
{
dynamic data = new { name = "李白", age = 20 };
return Json(data);
}
}
}
2. Ok()、Ok(T content)
namespace cms.Web.API
{
public class CeshiController : ApiController
{
public studentBLL bll = new studentBLL();
public IHttpActionResult GetList()
{
var list = bll.FindList();
return Ok(list);
}
public IHttpActionResult GetList2()
{
dynamic data = new { name = "李白", age = 20 };
return Ok(data);
}
public IHttpActionResult PostAdd()
{
//表示不向客户端返回任何信息,只告诉客户端请求成功
return Ok();
}
public IHttpActionResult GetModel(int id)
{
var model = bll.Find(id);
return Ok(model);
}
}
}
3. NotFound()
//找不到记录时使用
public IHttpActionResult GetModel(int id)
{
ar model = bll.Find(id);
if (model == null)
{
return NotFound();
}
return Ok(model);
}
4. Redirect(string location)
public IHttpActionResult GetCeshi(string name)
{
return Redirect("https://www.cnblogs.com/webapi/");
}
4· 其他类型
对于所有其他返回类型,WebAPI使用媒体格式化程序来序列化返回值,序列化方法可以在Accept头中来选择。WebAPI将序列化的值写入响应正文,响应状态代码为200(正常),但是无法直接发送错误代码。
public class ProductsController : ApiController
{
public IEnumerable<Product> Get()
{
return GetAllProductsFromDB();
}
}
//示例请求
GET http://localhost/api/products HTTP/1.1
User-Agent: Fiddler
Host: localhost:24127
Accept: application/json
//示例响应
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/8.0
Date: Mon, 27 Jan 2014 08:53:35 GMT
Content-Length: 56
[{"Id":1,"Name":"Yo-yo","Category":"Toys","Price":6.95}]