用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API
原文: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 :
| GET /api/todo | 獲取所有的to-do items | 無 | Array of to-do items |
| GET /api/todo/{id} | 通過ID獲取item | 無 | To-do item |
| POST /api/todo | 添加一個新的item | To-do item | To-do item |
| PUT /api/todo/{id} | 更新已經存在的item | To-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/todo,port?是一個隨機數。如果你使用 Chrome、Edge 或者 Firefox 瀏覽器,todo?數據將會被顯示。如果你使用 IE,IE 將會彈出窗口提示要求打開或者保存?todo.json?文件。
啟動 Fiddler,從?File?菜單,取消選擇?Capture Traffic?選項。這個會關閉捕獲 HTTP traffic。
選擇?Composer?頁面。在?Parsed?選項卡中,輸入?http://localhost:port/api/todo,port?是實際的端口號。點擊?Execute?發送請求。
結果會顯示在 sessions 列表中,響應碼是200。使用?Inspectors?選項卡來查看響應內容,包括請求正文。
實現其他的 CRUD 操作
最后一步是?Create、Update?以及?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 來創建和發送一個請求:
在?Composer?頁面,從下拉框選擇 POST。
在請求頭的文本框中, 添加?Content-Type: application/json,意思是?Content-Type?類型的頭信息值為?application/json。Fiddler 會自動添加 Content-Length 頭信息。
在請求正文的文本框,輸入以下內容:{"Name":"<你的 to-do 項目>"}
點擊?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 部署的問題, 請參考發布與部署。
查看或者下載示例代碼
相關文章:
ASP.NET Core 1.0 入門——了解一個空項目
ASP.NET Core 1.0 部署 HTTPS (.NET Framework 4.5.1)
.NET Core 1.0、ASP.NET Core 1.0和EF Core 1.0簡介
云服務器下ASP.NET Core 1.0環境搭建(包含mono與coreclr)
使用VS Code開發ASP.NET Core 應用程序
dotnet run是如何啟動asp.net core站點的
ASP.NET Core提供模塊化Middleware組件
“dotnet restore"和"dotnet run"都做了些什么?
探秘 dotnet run 如何運行 .NET Core 應用程序
.NET Portability Analyzer 已開源
ASP.NET Core的配置(1):讀取配置信息
ASP.NET Core的配置(2):配置模型詳解
.NET Core 1.0 RC2 歷險之旅
使用VS Code開發 調試.NET Core 應用程序
讓我們Core在一起:ASP.NET Core & .NET Core
.NET Core VS Code 環境配置
官方博客明確了 .NET Core RC2/RTM 時間表
.NET Core全新的配置管理[共9篇]
利用記事本創建一個ASP.NET Core RC2 MVC應用
微軟.NET 正式劈腿成功,橫跨所有平臺
.NET Core 1.0 CentOS7 嘗試
解讀發布:.NET Core RC2 and .NET Core SDK Preview 1
[.NET Core].NET Core R2安裝及示例教程
ASP.NET Core 開發-中間件(Middleware)
結合Jexus + Kestrel 部署 asp.net core 生產環境
通過Jexus 部署 dotnetcore版本MusicStore 示例程序
ASP.NET Core 中文文檔 第一章 入門
用 Visual Studio Code 在 macOS 上創建首個 ASP.NET Core 應用程序
原文地址:http://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-2_2-first-web-api.html
.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注
贊賞
人贊賞
總結
以上是生活随笔為你收集整理的用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RPC的发展历史
- 下一篇: ASP.NET Core MVC 与 V