.NET Core 創建 Web API

本教程介紹使用 ASP.NET Core 構建 Web API 的基礎知識。

本文章轉載微軟教程:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.1&tabs=visual-studio

在本教程中,你將瞭解:

  • 創建 Web API 項目。
  • 添加模型類和數據庫上下文。
  • 添加控制器。
  • 添加 CRUD 方法。
  • 配置路由和 URL 路徑。
  • 指定返回值。
  • 使用 Postman 調用 Web API。
  • 使用 JavaScript 調用 Web API。

在結束時,你會獲得可以管理存儲在關係數據庫中的“待辦事項”的 Web API。

概述

本教程將創建以下 API:

API 說明 請求正文 響應正文
GET /api/TodoItems 獲取所有待辦事項 待辦事項的數組
GET /api/TodoItems/{id} 按 ID 獲取項 待辦事項
POST /api/TodoItems 添加新項 待辦事項 待辦事項
PUT /api/TodoItems/{id} 更新現有項   待辦事項
DELETE /api/TodoItems/{id}     刪除項   

下圖顯示了應用的設計。

右側的框表示客戶端。

系統必備

 警告

如果使用 Visual Studio 2017,請參閱 dotnet/sdk 問題 #3124,以瞭解無法與 Visual Studio 一起使用的 .NET Core SDK 版本的信息。

創建 Web 項目

  • 從“文件”菜單中選擇“新建”>“項目” 。
  • 選擇“ASP.NET Core Web 應用程序”模板,再單擊“下一步” 。
  • 將項目命名爲 TodoApi,然後單擊“創建” 。
  • 在“創建新的 ASP.NET Core Web 應用程序”對話框中,確認選擇“.NET Core”和“ASP.NET Core 2.2” 。 選擇“API”模板,然後單擊“創建” 。 請不要選擇“啓用 Docker 支持” 。

VS“新建項目”對話框

測試 API

項目模板會創建 values API。 從瀏覽器調用 Get 方法以測試應用。

按 Ctrl+F5 運行應用。 Visual Studio 啓動瀏覽器並導航到 https://localhost:<port>/api/values,其中 <port> 是隨機選擇的端口號。

如果出現詢問是否應信任 IIS Express 證書的對話框,則選擇“是” 。 在接下來出現的“安全警告” 對話框中,選擇“是” 。

會返回以下 JSON:

JSON複製

["value1","value2"]

添加模型類

模型 是一組表示應用管理的數據的類。 此應用的模型是單個 TodoItem 類。

  • Visual Studio
  • 在“解決方案資源管理器” 中,右鍵單擊項目。 選擇“添加” > “新建文件夾” 。 將文件夾命名爲“Models” 。

  • 右鍵單擊“Models” 文件夾,然後選擇“添加” > “類” 。 將類命名爲 TodoItem,然後選擇“添加” 。

  • 將模板代碼替換爲以下代碼:

C#複製

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

Id 屬性用作關係數據庫中的唯一鍵。

模型類可位於項目的任意位置,但按照慣例會使用 Models 文件夾。

添加數據庫上下文

數據庫上下文是爲數據模型協調 Entity Framework 功能的主類 。 此類由 Microsoft.EntityFrameworkCore.DbContext 類派生而來。

  • Visual Studio
  • 右鍵單擊“Models” 文件夾,然後選擇“添加” > “類” 。 將類命名爲 TodoContext,然後單擊“添加” 。
  • 將模板代碼替換爲以下代碼:

    C#複製

    using Microsoft.EntityFrameworkCore;
    
    namespace TodoApi.Models
    {
        public class TodoContext : DbContext
        {
            public TodoContext(DbContextOptions<TodoContext> options)
                : base(options)
            {
            }
    
            public DbSet<TodoItem> TodoItems { get; set; }
        }
    }
    

註冊數據庫上下文

在 ASP.NET Core 中,服務(如數據庫上下文)必須向依賴關係注入 (DI) 容器進行註冊。 該容器向控制器提供服務。

使用以下突出顯示的代碼更新 Startup.cs :

// Unused usings removed
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using TodoApi.Models;

namespace TodoApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the 
        //container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<TodoContext>(opt =>
                opt.UseInMemoryDatabase("TodoList"));
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP 
        //request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                // The default HSTS value is 30 days. You may want to change this for 
                // production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseMvc();
        }
    }
}

前面的代碼:

  • 刪除未使用的 using 聲明。
  • 將數據庫上下文添加到 DI 容器。
  • 指定數據庫上下文將使用內存中數據庫。

添加控制器

  • 右鍵單擊 Controllers 文件夾。

  • 選擇“添加”>“新項” 。

  • 在“添加新項”對話框中,選擇“API 控制器類”模板 。

  • 將類命名爲 TodoController,然後選擇“添加” 。

    “添加新項”對話框,“控制器”顯示在搜索框中,並且“Web API 控制器”已選中

  • 將模板代碼替換爲以下代碼:

    C#複製

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.EntityFrameworkCore;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using TodoApi.Models;
    
    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;
    
            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();
                }
            }
        }
    }
    

前面的代碼:

  • 定義了沒有方法的 API 控制器類。
  • 使用 [ApiController] 屬性標記類。 此屬性指示控制器響應 Web API 請求。 有關該屬性啓用的特定行爲的信息,請參閱 使用 ASP.NET Core 創建 Web API
  • 使用 DI 將數據庫上下文 (TodoContext) 注入到控制器中。 數據庫上下文將在控制器中的每個 CRUD 方法中使用。
  • 如果數據庫爲空,則將名爲 Item1 的項添加到數據庫。 此代碼位於構造函數中,因此在每次出現新 HTTP 請求時運行。 如果刪除所有項,則構造函數會在下次調用 API 方法時再次創建 Item1。 因此刪除可能看上去不起作用,不過實際上確實有效。

添加 Get 方法

若要提供檢索待辦事項的 API,請將以下方法添加到 TodoController 類中:

C#複製

// GET: api/Todo
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
{
    return await _context.TodoItems.ToListAsync();
}

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

這些方法實現兩個 GET 終結點:

  • GET /api/todo
  • GET /api/todo/{id}

如果應用仍在運行,請停止它。 然後再次運行它以包括最新更改。

通過從瀏覽器調用兩個終結點來測試應用。 例如:

  • https://localhost:<port>/api/todo
  • https://localhost:<port>/api/todo/1

以下 HTTP 響應通過調用 GetTodoItems 來生成:

JSON複製

[
  {
    "id": 1,
    "name": "Item1",
    "isComplete": false
  }
]

路由和 URL 路徑

[HttpGet] 屬性表示響應 HTTP GET 請求的方法。 每個方法的 URL 路徑構造如下所示:

  • 在控制器的 Route 屬性中以模板字符串開頭:

    namespace TodoApi.Controllers
    {
        [Route("api/[controller]")]
        [ApiController]
        public class TodoController : ControllerBase
        {
            private readonly TodoContext _context;

  •     }

  • 將 [controller] 替換爲控制器的名稱,按照慣例,在控制器類名稱中去掉“Controller”後綴。 對於此示例,控制器類名稱爲“Todo”控制器,因此控制器名稱爲“todo” 。 ASP.NET Core 路由不區分大小寫。

  • 如果 [HttpGet] 屬性具有路由模板(例如 [HttpGet("products")]),則將它追加到路徑。 此示例不使用模板。 有關詳細信息,請參閱使用 Http [Verb] 特性的特性路由

在下面的 GetTodoItem 方法中,"{id}" 是待辦事項的唯一標識符的佔位符變量。調用 GetTodoItem 時,URL 中 "{id}" 的值會在 id 參數中提供給方法。

C#複製

// GET: api/Todo/5
[HttpGet("{id}")]
public async Task<ActionResult<TodoItem>> GetTodoItem(long id)
{
    var todoItem = await _context.TodoItems.FindAsync(id);

    if (todoItem == null)
    {
        return NotFound();
    }

    return todoItem;
}

返回值

GetTodoItems 和 GetTodoItem 方法的返回類型是 ActionResult<T> 類型。 ASP.NET Core 自動將對象序列化爲 JSON,並將 JSON 寫入響應消息的正文中。 在假設沒有未經處理的異常的情況下,此返回類型的響應代碼爲 200。 未經處理的異常將轉換爲 5xx 錯誤。

ActionResult 返回類型可以表示大範圍的 HTTP 狀態代碼。 例如,GetTodoItem 可以返回兩個不同的狀態值:

  • 如果沒有任何項與請求的 ID 匹配,則該方法將返回 404 NotFound 錯誤代碼。
  • 否則,此方法將返回具有 JSON 響應正文的 200。 返回 item 則產生 HTTP 200 響應。

測試 GetTodoItems 方法

本教程使用 Postman 測試 Web API。

  • 安裝 Postman
  • 啓動 Web 應用。
  • 啓動 Postman。
  • 禁用 SSL 證書驗證
  • 在“文件”>“設置”(“常規”選項卡)中,禁用“SSL 證書驗證” 。

 警告

在測試控制器之後重新啓用 SSL 證書驗證。

  • 創建新請求。
    • 將 HTTP 方法設置爲“GET” 。
    • 將請求 URL 設置爲 https://localhost:<port>/api/todo。 例如 https://localhost:5001/api/todo
  • 在 Postman 中設置Two pane view 。
  • 選擇Send

使用 Get 請求的 Postman

添加創建方法

在 Controllers / TodoController.cs 中添加以下 PostTodoItem 方法 :

C#複製

// 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);
}

前面的代碼是 HTTP POST 方法,如 [HttpPost] 屬性所指示。 該方法從 HTTP 請求正文獲取待辦事項的值。

CreatedAtAction 方法:

  • 如果成功,則返回 HTTP 201 狀態代碼。 HTTP 201 是在服務器上創建新資源的 HTTP POST 方法的標準響應。

  • 將 Location 標頭添加到響應。 Location 標頭指定新建的待辦事項的 URI。有關詳細信息,請參閱創建的 10.2.2 201

  • 引用 GetTodoItem 操作以創建 Location 標頭的 URI。 C# nameof 關鍵字用於避免在 CreatedAtAction 調用中硬編碼操作名稱。

    C#複製

    
     
    // GET: api/Todo/5 [HttpGet("{id}")] public async Task<ActionResult<TodoItem>> GetTodoItem(long id) { var todoItem = await _context.TodoItems.FindAsync(id); if (todoItem == null) { return NotFound(); } return todoItem; }

測試 PostTodoItem 方法

  • 生成項目。

  • 在 Postman 中,將 HTTP 方法設置爲 POST

  • 選擇“正文”選項卡 。

  • 選擇“原始”單選按鈕 。

  • 將類型設置爲 JSON (application/json)

  • 在請求正文中,輸入待辦事項的 JSON:

    JSON複製

    {
      "name":"walk dog",
      "isComplete":true
    }
    
  • 選擇Send

    使用創建請求的 Postman

    如果收到 405 不允許的方法錯誤,則可能是由於未在添加 PostTodoItem 方法之後編譯項目。

測試位置標頭 URI

  • Headers 窗格中選擇Response 選項卡。

  • 複製Location 標頭值:

    Postman 控制檯的“標頭”選項卡

  • 將方法設置爲“GET”。

  • 粘貼 URI(例如,https://localhost:5001/api/Todo/2)。

  • 選擇Send

添加 PutTodoItem 方法

添加以下 PutTodoItem 方法:

C#複製

// PUT: api/Todo/5
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem item)
{
    if (id != item.Id)
    {
        return BadRequest();
    }

    _context.Entry(item).State = EntityState.Modified;
    await _context.SaveChangesAsync();

    return NoContent();
}

PutTodoItem 與 PostTodoItem 類似,但是使用的是 HTTP PUT。 響應是 204(無內容)。 根據 HTTP 規範,PUT 請求需要客戶端發送整個更新的實體,而不僅僅是更改。 若要支持部分更新,請使用 HTTP PATCH

如果在調用 PutTodoItem 時出錯,請調用 GET 以確保數據庫中有項目。

測試 PutTodoItem 方法

本示例使用內存內、數據庫,每次啓動應用時都必須對其進行初始化。 在進行 PUT 調用之前,數據庫中必須有一個項。 調用 GET,以確保在調用 PUT 之前數據庫中存在項目。

更新 id = 1 的待辦事項並將其名稱設置爲“feed fish”:

JSON複製

  {
    "ID":1,
    "name":"feed fish",
    "isComplete":true
  }

下圖顯示 Postman 更新:

顯示 204(無內容)響應的 Postman 控制檯

添加 DeleteTodoItem 方法

添加以下 DeleteTodoItem 方法:

C#複製

// DELETE: api/Todo/5
[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();
}

DeleteTodoItem 響應是 204(無內容)

測試 DeleteTodoItem 方法

使用 Postman 刪除待辦事項:

  • 將方法設置爲 DELETE
  • 設置要刪除的對象的 URI,例如 https://localhost:5001/api/todo/1
  • 選擇Send

可通過示例應用刪除所有項。 但如果刪除最後一項,則在下次調用 API 時,模型類構造函數會創建一個新項。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章