天津渔网价格虚拟社区

用Visual Studio 和ASP.NET Core MVC 创建首个 Web API

dotNET跨平台2018-09-16 10:33:27

原文:Building Your First Web API with ASP.NET Core MVC and Visual Studio
作者:Mike Wasson 和 Rick Anderson
翻译:谢炀(kiler)
校对:何镇汐刘怡(AlexLEWIS)

HTTP 协议不仅仅提供网页服务。它也是一个构建公开服务和数据 API 的强大平台。HTTP 协议是简单、灵活、无处不在的。几乎你能想到的任何平台上都有 HTTP 支持,所以 HTTP 服务能够发送到多种客户端, 包括浏览器,移动设备和传统的桌面应用程序。

在本教程中,你将创建一个简单的 Web API 来管理一个 "to-do" 列表。在本教程中你无需编写任何 UI 代码。

ASP.NET Core 已经内置了用 MVC 架构 构建 Web API 的支持。统一了两个框架使得它易于构建应用程序,包括用户界面(HTML)和 API,因为现在它们共享相同的代码库和管道。

注意
如果你想把一个老的 Web API 应用程序迁移到 ASP.NET Core, 参考从 ASP.NET Web API 迁移

总览

这是你需要创建的 API :

API描述请求正文响应正文
GET /api/todo获取所有的to-do itemsArray of to-do items
GET /api/todo/{id}通过ID获取itemTo-do item
POST /api/todo添加一个新的itemTo-do itemTo-do item
PUT /api/todo/{id}更新已经存在的itemTo-do item
DELETE /api/todo/{id}删除指定的item

下面的图表展示了应用程序的基本设计:

  • 不管是哪个调用 API 的客户端(浏览器、移动应用等)。我们不会在本教程编写客户端。

  • model 是一个代表你应用程序数据的类。在本案例中,只有一个模型 to-do 项。模型表现为简单 C# 类型 (POCOs),

  • controller 是一个处理 HTTP 请求并返回 HTTP 响应的对象。这个示例程序将只会有一个 controller。

  • 为了保证教程简单我们不使用数据库。作为替代,我们会把 to-do 项存入内存。但是我们依然包含了一个数据访问层(不重要的),用来隔离 Web API和数据层。如果想使用数据库,参考用 Visual Studio 创建 ASP.NET Core MVC 应用程序

安装 Fiddler

我们不创建客户端,我们使用 Fiddler 来测试 API。Fiddler 是一个 Web 调试工具可以让您撰写的 HTTP 请求进行发送并查看原始的 HTTP 响应。

创建项目

启动 Visual Studio。从 File 菜单, 选择 New > Project

选择 ASP.NET Core Web Application 项目模版。项目命名为 TodoApi 并且点击 OK

在 New ASP.NET Core Web Application (.NET Core) - TodoApi 对话框中,选择 Web API 模版。点击 OK

添加模型类

模型表示应用程序中的数据的对象。在本示例中,唯一使用到的模型是一个 to-do 项。

添加一个名为 "Models" 的目录。在解决方案浏览器中, 右击项目。选择 Add > New Folder。把目录名命名为 Models

注意
你可以把模型类放到项目的任何地方,但是 Models 是约定的默认目录。

下一步,添加一个 TodoItem 类。右击 Models 目录并选择 Add > New Item

在 Add New Item 对话框中,选择 Class 模版。命名类为 TodoItem 并点击 OK

将生成代码替换为:

namespace TodoApi.Models{  
 public class TodoItem    {        
 public string Key { get; set; }      
   public string Name { get; set; }    
       public bool IsComplete { get; set; }    } }

添加仓储类

repository 类是一个封装了数据层的类,包含了获取数据并映射到实体模型类的业务逻辑。 尽管本例中不使用数据库,但依旧值得去思考 Repository 是如何注入到我们的 Controller 的。在 Models 目录下创建 repository 代码。

定义一个名为 ITodoRepository 的 repository 接口. 通过类模版 (Add New Item > Class)。

using System.Collections.Generic;
namespace TodoApi.Models{  
 public interface ITodoRepository    {      
  void Add(TodoItem item);    
     IEnumerable<TodoItem> GetAll();    
        TodoItem Find(string key);      
         TodoItem Remove(string key);  
              void Update(TodoItem item);    } }

接口定义了基本的 CRUD 操作。

下一步,添加一个实现 ITodoRepository 接口的 TodoRepository 类:

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;

namespace TodoApi.Models{    
   public class TodoRepository : ITodoRepository    {        
static ConcurrentDictionary<string, TodoItem> _todos =              new ConcurrentDictionary<string, TodoItem>();    

   public TodoRepository()        {            Add(new TodoItem { Name = "Item1" });        }        public IEnumerable<TodoItem> GetAll()        {    
          return _todos.Values;        }      
   
     public void Add(TodoItem item)        {            item.Key = Guid.NewGuid().ToString();            _todos[item.Key] = item;        }        
     
     public TodoItem Find(string key)        {            TodoItem item;            _todos.TryGetValue(key, out item);            return item;        }        
     
     public TodoItem Remove(string key)        {            TodoItem item;            _todos.TryGetValue(key, out item);            _todos.TryRemove(key, out item);            return item;        }      
     
      public void Update(TodoItem item)        {            _todos[item.Key] = item;        }    } }

生成应用程序确保没有任何编译错误。

注册仓储

定义 repository 接口, 我们可以从使用它的 MVC Controller 解耦仓储类,而不是直接在 Controller 里面实例化 TodoRepository ,我们将会用 ASP.NET Core 内置功能注入 ITodoRepository ,更多请参考依赖注入

这种方式可以更容易地对你的 Controller 进行单元测试。单元测试应该注入一个 Mock 或 stub 的 ITodoRepository。通过这样的方式测试范围可以限制在业务逻辑层而非数据访问层。

为了注入 repository 到 controller,我们必须注册DI容器。打开 Startup.cs 文件。添加以下指令:

using TodoApi.Models;

在 ConfigureServices 方法中,添加高亮方法:

public void ConfigureServices(IServiceCollection services){  // Add framework services.
  services.AddMvc();  // Add our repository type,下行高亮
  services.AddSingleton<ITodoRepository, TodoRepository>();
}

添加控制器

在解决方案浏览器中,右击 Controllers 目录。选择 Add > New Item。在 Add New Item 对话框中,选择 Web API Controller Class 模版。命名为 TodoController

将生成的代码替换为如下代码:

using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using TodoApi.Models;
namespace TodoApi.Controllers{  [Route("api/[controller]")]  
public class TodoController : Controller  {    
public TodoController(ITodoRepository todoItems)    {      TodoItems = todoItems;    }    public ITodoRepository TodoItems { get; set; }  } }

这里定义了一个空的 controller 类。下一个章节,我们将添加代码来实现 API。

获取 to-do 列表

为了获取 to-do 项,添加下列方法到 TodoController 类。

public IEnumerable<TodoItem> GetAll(){    return TodoItems.GetAll();
}

[HttpGet("{id}", Name = "GetTodo")]public IActionResult GetById(string id){  var item = TodoItems.Find(id);  if (item == null)
  {    return NotFound();
  }  return new ObjectResult(item);
}

以下是 GetAll 方法 HTTP 响应:

HTTP/1.1 200 OKContent-Type: application/json; charset=utf-8Server: Microsoft-IIS/10.0Date: Thu, 18 Jun 2015 20:51:10 GMTContent-Length: 82[{"Key":"4f67d7c5-a2a9-4aae-b030-16003dd829ae","Name":"Item1","IsComplete":false}]

在后面的教程中,我将会告诉你如何使用 Fiddler 工具查看 HTTP 响应。

路由和 URL 路径

[HttpGet] 标签指定这些方法均为 HTTP GET 方法。每个方法构建的 Url 如下:

  • 替换 controller 模版里面的路由标签,[Route("api/[controller]")]

  • 把 "[Controller]" 替换为控制器名,必须是带 "Controller" 后缀的小写名称。在本示例里面控制器的名字为 "todo"(不区分大小写)。对于这个例子,controller 的类名是 TodoController 并且根名是 "todo"。ASP.NET MVC Core 是需要区分大小写的。

  • 如果 [HttpGet] 标签有模版字符串,附加到路径。本示例没有模版字符串。

对于 GetById 方法,在实际的 HTTP 请求中 "{id}" 是一个占位符,客户端在运行时会使用 todo 项的 ID 属性,当 MVC 调用 GetById,会把 "{id}" 占位符分配到 Url 方法的 id 参数上去。

更换 "api/todo" 的启动 Url

  • 右击项目 > Properties

  • 选择 Debug 选项卡变更 "api/todo" Launch URL 设置

了解更多有关请求路由的信息请参考路由到控制器 Action

返回值

GetAll 方法返回一个 CLR 对象。MVC 自动把对象序列化为 JSON 并把 JSON 对象写入响应消息正文。响应状态码为 200,假设没有未处理异常的情况下。(未处理异常一般会被转化为 5xx 错误。)

相反,GetById 将会返回一个 IActionResult 类型,代表一个更加通用的结果对象。因为 GetById 有两个不同的返回值:

  • 如果没有数据项可以匹配 ID,方法会返回 404 错误,并最终以返回 NotFound 告终。

  • 否则方法会返回 200 以及 JSON 响应正文。并最终以返回 ObjectResult 告终。


使用 Fiddler 调用 API

这一步是可选的,但是有助于我们查看 Web API 返回的原始 HTTP 响应。

在 Visual Studio 中,点击 ^F5 启动项目。Visual Studio 启动浏览器并导航到 http://localhost:port/api/todoport 是一个随机数。如果你使用 Chrome、Edge 或者 Firefox 浏览器,todo 数据将会被显示。如果你使用 IE,IE 将会弹出窗口提示要求打开或者保存 todo.json 文件。

启动 Fiddler,从 File 菜单,取消选择 Capture Traffic 选项。这个会关闭捕获 HTTP traffic。

选择 Composer 页面。在 Parsed 选项卡中,输入 http://localhost:port/api/todoport 是实际的端口号。点击 Execute 发送请求。

结果会显示在 sessions 列表中,响应码是200。使用 Inspectors 选项卡来查看响应内容,包括请求正文。

实现其他的 CRUD 操作

最后一步是 CreateUpdate 以及 Delete 方法到 Controller。这些方法都是围绕着一个主题,所以我将只列出代码以及标注出主要的区别。

Create

[HttpPost]
public IActionResult Create([FromBody] TodoItem item)
{    if (item == null)    {        return BadRequest();    }    TodoItems.Add(item);  

 return CreatedAtRoute("GetTodo", new { controller = "Todo", id = item.Key }, item); }

这是一个 HTTP POST 方法,用 [HttpPost] 标签声明。[FromBody] 标签告诉 MVC 从 HTTP 请求的正文中获取 to-do 项的值。

当通过 CreatedAtRoute 方法向服务器发出 HTTP POST 方法以创建新资源时,将返回标准的 201 响应。CreateAtRoute 还把 Location 头信息加入到了响应。Location 头信息指定新创建的 todo 项的 URI。查看 10.2.2 201 Created

我们使用 Fiddler 来创建和发送一个请求:

  1. 在 Composer 页面,从下拉框选择 POST。

  2. 在请求头的文本框中, 添加 Content-Type: application/json,意思是 Content-Type 类型的头信息值为 application/json。Fiddler 会自动添加 Content-Length 头信息。

  3. 在请求正文的文本框,输入以下内容:{"Name":"<你的 to-do 项目>"}

  4. 点击 Execute

这是一个简单的 HTTP 会话. 使用 Raw 选项卡查看会话数据.

Request:

POST http://localhost:29359/api/todo HTTP/1.1User-Agent: FiddlerHost: localhost:29359Content-Type: application/jsonContent-Length: 33{"Name":"Alphabetize paperclips"}

Response:

HTTP/1.1 201 CreatedContent-Type: application/json; charset=utf-8Location: http://localhost:29359/api/Todo/8fa2154d-f862-41f8-a5e5-a9a3faba0233Server: Microsoft-IIS/10.0Date: Thu, 18 Jun 2015 20:51:55 GMTContent-Length: 97{"Key":"8fa2154d-f862-41f8-a5e5-a9a3faba0233","Name":"Alphabetize paperclips","IsComplete":false}

Update

[HttpPut("{id}")]
public IActionResult Update(string id, [FromBody] TodoItem item)
{  
    if (item == null || item.Key != id)    {    
          return BadRequest();   }  
var todo = TodoItems.Find(id);  if (todo == null)  {    return NotFound();  }  TodoItems.Update(item);
 return new NoContentResult(); }

Update 类似于 Create,但是使用 HTTP PUT。响应是 204 (No Content)。根据 HTTP 规范,PUT 请求要求客户端发送整个实体更新,而不仅仅是增量。为了支持局部更新,请使用 HTTP PATCH。

Delete

[HttpDelete("{id}")]
public void Delete(string id){  TodoItems.Remove(id); }

方法返回 204 (无内容) 响应。这意味着客户端会收到 204 响应即使该项目已被删除,或者根本不存在。有两种方法来处理请求删除不存在资源的问题:

  • "Delete" 代表「删除一个已存在的项」,如果不存在返回 404。

  • "Delete" 代表「确保该项不在集合中」,如果项目不在集合中返回 204。

无论哪种方法是合理的。如果收到 404 错误,客户端将需要处理这种情况。

下一步

  • 关于如何为原生移动 App 创建后端, 请参考为原生移动应用创建后台服务

  • 更多关于 API 部署的问题, 请参考发布与部署

  • 查看或者下载示例代码

相关文章:


原文地址:http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-2_2-first-web-api.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注