HTTP不单单用于提供网页。HTTP也是构建公开服务和数据的API强大平台。HTTP简单灵活且无处不在。几乎任何你能想到的平台都有一个HTTP库,所以HTTP服务能够覆盖普遍的客户端,包括浏览器,移动设备和传统的桌面应用程序。web
ASP.NET Web API 是一个框架,基于.NET Framework 或.NET Core 之上构建 Web API。sql
从本章开始学习Web API系列时,先从一个示例开始,下面使用ASP.NET Core MVC 建立 Web API。经过本次演示将了解到一个基础的Web API应用。环境使用vs 2017 +sql server 2012。示例主要知识点包括:数据库
(1)建立 Web API 项目。json
(2)添加模型类。api
(3)建立数据库上下文。浏览器
(4)注册数据库上下文。服务器
(5)添加控制器。框架
(6)添加 CRUD 方法。asp.net
(7)配置路由和 URL 路径。async
(8)指定返回值。
(9)使用Fiddle调用 Web API。
(10)使用 jQuery 调用 Web API。
在开发Web API以前,先制定几个有针对性的API 接口,至于api 接口业务很简单,主要是演示如何应用Web API。
API接口 |
说明 |
请求报文 |
响应报文 |
GET /api/todo |
获取全部待办事项 |
无 |
待办事项的数据 |
GET /api/todo/{id} |
按 ID 获取项 |
无 |
待办事项 |
POST /api/todo |
添加新项 |
待办事项 |
待办事项 |
PUT /api/todo/{id} |
更新现有项 |
待办事项 |
无 |
DELETE /api/todo/{id} |
删除项 |
无 |
无 |
1.1 建立web项目
(1)从“文件”菜单中选择“新建” > “项目”。
(2)选择“ASP.NET Core Web 应用程序”模板。 将项目命名为 TodoApi,而后单击“肯定”。
(3)在“新建 ASP.NET Core Web 应用程序 - TodoApi”对话框中,选择 ASP.NET Core 版本。 选择“API”模板,而后单击“肯定”。 请不要选择“启用 Docker 支持”。
项目模板会建立 values
API。 控制器方法中默认的Http[Verb] 属性路由包括GET,POST, PUT, DELETE接口
1.2 添加模型类
在项目中,添加Models文件夹,新建一个 TodoItem
类,以下所示:
public class TodoItem { //主键 public long Id { get; set; } //待办事项名称 public string Name { get; set; } //是否完成 public bool IsComplete { get; set; } }
1.3 添加数据库上下文
在“Models”文件夹,而后选择“添加” > “类”。 将类命名为 TodoContext,以下所示:
//using Microsoft.EntityFrameworkCore; public class TodoContext: DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } }
1.4 注册上下文
在 ASP.NET Core 中,服务(如数据库上下文)必须向依赖关系注入 (DI) 容器进行注册。 该容器向控制器提供服务。这里使用Microsoft.EntityFrameworkCore.SqlServer数据提供程序。再根据模型生成数据库表(库名Todo,有一个表TodoItem)。关于如何安装数据提供程序,以及如何用模型生成数据库表,请参考“asp.net core 系列第 20 篇” 。使用迁移生成数据库后,以下所示:
1.5 添加控制器
在Controllers 文件夹中,选择“API 控制器类”模板。将类命名为 TodoController.cs, 代码以下所示:
[Route("api/[controller]")] [ApiController]//添加特性,表明是一个Web API控制器类 public class TodoController : Controller { private readonly TodoContext _context; /// <summary> /// 实例化一个EF上下文,进行数据库操做。开始初始入库一条数据 /// </summary> /// <param name="context"></param> public TodoController(TodoContext context) { _context = context; if (_context.TodoItems.Count() == 0) { // Create a new TodoItem if collection is empty, // which means you can't delete all TodoItems. _context.TodoItems.Add(new TodoItem { Name = "Item1" }); _context.SaveChanges(); } } }
1.6 添加GET方法
经过GET方法来查询待办事项的 API,将如下方法添加到 TodoController 类中。关于路由知识,请参考asp.net core 系列第5篇。
/// <summary> /// 获取全部事项 /// GET: api/Todo /// </summary> /// <returns></returns> [HttpGet] public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() { //using Microsoft.EntityFrameworkCore; return await _context.TodoItems.ToListAsync(); } /// <summary> /// 根据id,获取一条事项 /// GET: api/Todo/5。 id 是参数,表明路由合并 /// </summary> /// <param name="id"></param> /// <returns></returns> [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }
启动vs,测试结果,以下所示,注意请求wep api 地址与action的方法名没有关系,是根据方法名之上的Http[Verb]特性来肯定url地址的:
1.7 路由和URL路径
(1) Route特性
Route是用来制定路由模板的,在第5章中也讲到。[Route("api/[controller]")]中是以api开头,替换[controller]
为控制器的名称, 按照惯例,控制器类名称减去“Controller”后缀, 所以控制器名称为“todo” ,路由不区分大小写。
(2) HttpGet
若是[HttpGet]
属性具备路径模板,例如:[HttpGet("{id}")]
,
则将其
附加到路径
(如:api/todo/1)
。在这个示例中
,
"{id}"
是占位符变量,用于待办事项的惟一标识符。
1.8 返回值
上面的GetTodoItems和GetTodoItem方法的返回类型是ActionResult <T>类型。ASP.NET Core自动将对象序列化为JSON,并将JSON写入响应消息的正文中。假设没有异常,此返回类型的响应代码为200。未处理的异常被转换为5xx错误。
ActionResult
返回类型能够表示各类HTTP状态代码,例如在上面的GetTodoItem
方法中
能够返回两个不一样的状态值:一个是成功的200, 一个是404未到找。全部的HTTP状态代码能够在ControllerBase中找到,例以下图中的Forbid() 是Http状态码403,NoContent()是Http 状态码204 。 等等
下面简单使用Fiddler来测试一下增删改增。先在本机vs 2017中启动该项目,地址为http://localhost:62271。
2.1 查询
在Fiddler工具中,选择GET,输入查询的http地址,右边是响应的http 状态码200, 以及查询的json结构对象。
2.2 新增
下面建立方法,添加如下 PostTodoItem 方法,在新增方法中调用了CreatedAtAction内置方法,若是新增成功,则返回 HTTP 201 状态代码。HTTP 201是HTTP POST方法的标准响应,该方法在服务器上建立新资源。
//POST: api/Todo [HttpPost] public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem item) { _context.TodoItems.Add(item); await _context.SaveChangesAsync(); return CreatedAtAction(nameof(GetTodoItem), new { id = item.Id }, item); }
2.3 修改
添加如下 PutTodoItem
方法, PutTodoItem 与 PostTodoItem 相似,可是使用的是 HTTP PUT。 响应是 204(无内容)。 根据 HTTP 规范,PUT 请求须要客户端发送整个更新的实体,而不单单是更改。若要支持部分更新,请使用HttpPatch特性。
// PUT: api/Todo/1 [HttpPut("{id}")] public async Task<IActionResult> PutTodoItem(long id, TodoItem item) { if (id != item.Id) { //http 403 return BadRequest(); } //当前传过来的实体添加到上下文,并设置为修改 _context.Entry(item).State = EntityState.Modified; await _context.SaveChangesAsync(); return NoContent(); }
2.4 删除
// DELETE: api/Todo/2 [HttpDelete("{id}")] public async Task<IActionResult> DeleteTodoItem(long id) { var todoitem = await _context.TodoItems.FindAsync(id); if (todoitem == null) { return NotFound(); } _context.TodoItems.Remove(todoitem); await _context.SaveChangesAsync(); return NoContent(); }
最后:关于jQuery 调用 Web API,再也不演示,jQuery调用的配置和注意事项,请查看官网介绍。
参考文献: