教學課程:使用 ASP.NET Core 建立 Web API
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
作者:Rick Anderson 與 Kirk Larkin
本教學課程將教導建置使用資料庫之控制器型 Web API 的基本概念。 在 ASP.NET Core 中建立 API 的另一種方法是建立最小的 API。 如需在基本 API 與控制器型 API 之間選擇的說明,請參閱 API 概觀。 如需建立最小 API 的教學課程,請參閱教學課程:使用 ASP.NET Core 建立最小 API。
概觀
本教學課程會建立以下 API:
API | 描述 | 要求本文 | 回應本文 |
---|---|---|---|
GET /api/todoitems |
取得所有待辦事項 | 無 | 待辦事項的陣列 |
GET /api/todoitems/{id} |
依識別碼取得項目 | 無 | 待辦事項 |
POST /api/todoitems |
新增記錄 | 待辦事項 | 待辦事項 |
PUT /api/todoitems/{id} |
更新現有的項目 | 待辦事項 | 無 |
DELETE /api/todoitems/{id} |
刪除項目 | 無 | 無 |
下圖顯示應用程式的設計。
必要條件
Visual Studio 2022 和 ASP.NET 與 Web 開發工作負載。
建立 Web 專案
- 從 [檔案] 功能表選取 [新增] >[專案] 。
- 在搜尋方塊中輸入 Web API。
- 選取 ASP.NET Core Web API 範本,然後選取 [下一步]。
- 在 [設定新專案] 對話方塊中,將專案命名為 TodoApi,然後選取 [下一步]。
- 在 [其他資訊] 對話方塊中:
- 確認 Framework 為 .NET 8.0 (長期支援)。
- 確認已核取 [使用控制器 (取消核取以使用最小 API)] 核取方塊。
- 確認已核取 [啟用 OpenAPI 支援] 核取方塊。
- 選取建立。
新增 NuGet 套件
必須新增 NuGet 套件,才能支援本教學課程中使用的資料庫。
- 在 [工具] 功能表上,選取 [NuGet 套件管理員] > [管理解決方案的 NuGet 套件]。
- 選取 [瀏覽] 索引標籤。
- 在搜尋方塊中輸入 Microsoft.EntityFrameworkCore.InMemory,然後選取
Microsoft.EntityFrameworkCore.InMemory
。 - 選取右窗格中的 [專案] 核取方塊,然後選取 [安裝]。
注意
如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件) 的安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。
測試專案
專案範本會建立支援 Swagger 的 WeatherForecast
API。
按 Ctrl+F5 即可執行而不使用偵錯工具。
當專案尚未設定為使用 SSL 時,Visual Studio 會顯示下列對話方塊:
如果您信任 IIS Express SSL 憑證,請選取 [是]。
此時會顯示下列對話方塊:
若您同意信任開發憑證,請選取 [是]。
如需關於信任 Firefox 瀏覽器的資訊,請參閱 Firefox SEC_ERROR_INADEQUATE_KEY_USAGE 憑證錯誤。
Visual Studio 會啟動預設瀏覽器並瀏覽至 https://localhost:<port>/swagger/index.html
,其中 <port>
是專案建立時設定的隨機選擇連接埠號碼。
Swagger 頁面 /swagger/index.html
隨即顯示。 選取 [GET]>[試用]>[執行]。 頁面會顯示:
- 用來測試 WeatherForecast API 的 Curl 命令。
- 用來測試 WeatherForecast API 的 URL。
- 回應碼、本文和標頭。
- 具有媒體類型與範例值和架構的下拉式清單方塊。
如果 Swagger 頁面未出現,請參閱這個 GitHub 問題。
Swagger 可用來為 Web API 產生有用的文件和說明頁面。 本教學課程會使用 Swagger 來測試應用程式。 如需 Swagger 的詳細資訊,請參閱使用 ASP.NET Core Web API 文件搭配 Swagger / OpenAPI。
複製並貼上瀏覽器中的要求 URL:https://localhost:<port>/weatherforecast
系統會傳回類似下列範例的 JSON:
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
新增模型類別
「模型」是代表應用程式所管理資料的一組類別。 此應用程式的模型是 TodoItem
類別。
- 在 [方案總管] 中,以滑鼠右鍵按一下專案。 選取 [新增]>[新增資料夾]。 將資料夾命名為
Models
註冊免費試用帳戶。 - 以滑鼠右鍵按一下
Models
資料夾並選取 [新增]>[類別]。 將類別命名為 TodoItem,然後選取 [新增]。 - 以下列項目取代範本程式碼:
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 類別來建立。
- 以滑鼠右鍵按一下
Models
資料夾並選取 [新增]>[類別]。 將類別命名為 TodoContext,然後按一下 [新增]。
輸入下列程式碼:
using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } = null!; }
登錄資料庫內容
在 ASP.NET Core 中,資料庫內容等服務必須向相依性插入 (DI) 容器註冊。 此容器會將服務提供給控制器。
使用下列醒目提示的程式碼更新 Program.cs
:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
上述 程式碼:
- 加入
using
指示詞。 - 將資料庫內容新增至 DI 容器。
- 指定資料庫內容將會使用記憶體內部資料庫。
Scaffold 控制器
以滑鼠右鍵按一下
Controllers
資料夾。選取 [新增]。
選取 [使用 Entity Framework 執行動作的 API 控制器],然後選取 [新增]。
在 [使用 Entity Framework 執行動作的 API 控制器] 對話方塊中:
- 在 [模型類別] 中選取 [TodoItem (TodoApi.Models)]。
- 在 [資料內容類別] 中選取 [TodoContext (TodoApi.Models)]。
- 選取新增。
如果 Scaffolding 作業失敗,請選取 [新增] 以嘗試第二次 Scaffolding。
產生的程式碼:
- 使用
[ApiController]
屬性標記類別。 這個屬性表示控制器會回應 Web API 要求。 如需屬性啟用的特定行為相關資訊,請參閱 使用 ASP.NET Core 建立 Web API。 - 使用 DI 將資料庫內容 (
TodoContext
) 插入到控制器中。 控制器中的每一個 CRUD 方法都會使用資料庫內容。
ASP.NET Core 範本適用於:
- 路由範本中檢視包含
[action]
的控制器。 - API 控制器在路由範本中不包含
[action]
。
當 [action]
權杖不在路由範本中時,動作名稱 (方法名稱) 不會包含在端點中。 也就是說,動作的相關聯方法名稱不會用於比對路由。
更新 PostTodoItem 建立方法
更新 PostTodoItem
中的 return 陳述式,以使用 nameof 運算子:
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}
上述程式碼是 HTTP POST
方法,以 [HttpPost]
屬性表示。 該方法會從 HTTP 要求本文取得 TodoItem
的值。
如需詳細資訊,請參閱使用 Http[Verb] 屬性的屬性路由。
CreatedAtAction 方法:
- 成功時會傳回 HTTP 201 狀態碼。 對於可在伺服器上建立新資源的
HTTP POST
方法,HTTP 201
是標準回應。 - 將 Location標頭新增到回應。
Location
標頭會指定新建待辦事項的 URI。 如需詳細資訊,請參閱 10.2.2 201 Created (已建立 10.2.2 201)。 - 參考
GetTodoItem
動作以建立Location
標頭的 URI。 C#nameof
關鍵字是用來避免在CreatedAtAction
呼叫中以硬式編碼方式寫入動作名稱。
測試 PostTodoItem
按 Ctrl+F5 執行應用程式。
在 Swagger 瀏覽器視窗中,選取 [POST /api/TodoItems],然後選取 [試用]。
在要求本文輸入視窗中,更新 JSON。 例如,
{ "name": "walk dog", "isComplete": true }
選取 [執行]
測試位置標頭 URI
在上述 POST 中,Swagger UI 會顯示 [回應] 標頭底下的位置標頭。 例如: location: https://localhost:7260/api/TodoItems/1
。 位置標頭會顯示所建立資源的 URI。
若要測試位置標頭:
在 Swagger 瀏覽器視窗中,選取 [GET /api/TodoItems/{id}],然後選取 [試用]。
在
id
輸入方塊中輸入1
,然後選取 [執行]。
檢查 GET 方法
兩個 GET 端點即會實作:
GET /api/todoitems
GET /api/todoitems/{id}
上一節顯示 /api/todoitems/{id}
路由的範例。
依照 POST 指示新增另一個待辦事項,然後使用 Swagger 測試 /api/todoitems
路由。
這個應用程式會使用記憶體內部資料庫。 如果應用程式在停止後再啟動,上述 GET 要求不會傳回任何資料。 如果沒有傳回任何資料,請將資料 POST 到應用程式。
傳送和 URL 路徑
[HttpGet]
屬性代表回應 HTTP GET
要求的方法。 每個方法的 URL 路徑的建構方式如下:
一開始在控制器的
Route
屬性中使用範本字串:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase
以控制器的名稱取代
[controller]
,也就是將控制器類別名稱減去 "Controller" 字尾。 在此範例中,控制器類別名稱是 TodoItemsController,因此控制器名稱是 "TodoItems"。 ASP.NET Core 路由不區分大小寫。如果
[HttpGet]
屬性具有路由範本 (例如[HttpGet("products")]
),請將其附加到路徑。 此範例不使用範本。 如需詳細資訊,請參閱使用 Http[Verb] 屬性的屬性路由。
在下列 GetTodoItem
方法中,"{id}"
是待辦事項唯一識別碼的預留位置變數。 在叫用 GetTodoItem
時,會將 URL 中的 "{id}"
值提供給方法的 id
參數。
[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 OK,假設沒有任何未處理的例外狀況。 未處理的例外狀況會轉譯成 5xx 錯誤。
ActionResult
傳回型別可代表各種 HTTP 狀態碼。 例如,GetTodoItem
可傳回兩個不同的狀態值:
PutTodoItem 方法
檢查 PutTodoItem
方法:
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
PutTodoItem
類似於 PostTodoItem
,但是會使用 HTTP PUT
。 回應是 204 (No Content) (204 (沒有內容))。 根據 HTTP 規格,PUT
要求需要用戶端傳送整個更新的實體,而不只是變更。 若要支援部分更新,請使用 HTTP PATCH。
測試 PutTodoItem 方法
此範例使用在每次應用程式啟動都必須初始化的記憶體內部資料庫。 資料庫中必須有項目,您才能進行 PUT 呼叫。 在發出 PUT 呼叫之前,呼叫 GET 以確保資料庫中有項目。
使用 Swagger UI,使用 PUT 按鈕來更新識別碼為 1 的 TodoItem
,並將其名稱設定為 "feed fish"
。 請注意,回應為 HTTP 204 No Content
。
DeleteTodoItem 方法
檢查 DeleteTodoItem
方法:
[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 方法
使用 Swagger UI 刪除識別碼為 1 的 TodoItem
。 請注意,回應為 HTTP 204 No Content
。
使用其他工具進行測試
還有其他許多工具可用來測試 Web API,例如:
- Visual Studio 端點總管和 .http 檔案
- http-repl
- curl。 Swagger 會使用
curl
並顯示其提交的curl
命令。 - Fiddler
如需詳細資訊,請參閱
防止過度張貼
目前範例應用程式會公開整個 TodoItem
物件。 生產應用程式通常會限制輸入的資料,並使用模型的子集傳回。 背後有多個原因,而安全性是主要原因。 模型的子集通常稱為資料傳輸物件 (DTO)、輸入模型或檢視模型。 本教學課程中使用 DTO。
DTO 可用來:
- 防止過度張貼。
- 隱藏用戶端不應該檢視的屬性。
- 省略一些屬性,以減少承載大小。
- 包含巢狀物件的壓平合併物件圖形。 壓平合併物件圖形對用戶端會更方便。
若要示範 DTO 方法,請更新 TodoItem
類別以包含祕密欄位:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
}
祕密欄位必須從此應用程式隱藏,但系統管理應用程式可以選擇公開它。
確認您可以張貼並取得祕密欄位。
建立 DTO 模型:
namespace TodoApi.Models;
public class TodoItemDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
更新 TodoItemsController
以使用 TodoItemDTO
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
// GET: api/TodoItems/5
// <snippet_GetByID>
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
// </snippet_GetByID>
// PUT: api/TodoItems/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Update>
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
{
if (id != todoDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoDTO.Name;
todoItem.IsComplete = todoDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// </snippet_Update>
// POST: api/TodoItems
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Create>
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoDTO.IsComplete,
Name = todoDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// </snippet_Create>
// DELETE: api/TodoItems/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();
}
private bool TodoItemExists(long id)
{
return _context.TodoItems.Any(e => e.Id == id);
}
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
new TodoItemDTO
{
Id = todoItem.Id,
Name = todoItem.Name,
IsComplete = todoItem.IsComplete
};
}
確認您無法張貼或取得祕密欄位。
使用 JavaScript 呼叫 Web API
請參閱教學課程:使用 JavaScript 呼叫 ASP.NET Core Web API。
Web API 影片系列
請參閱影片:初學者系列:Web API。
可靠的 Web 應用程式模式
請參閱 The Reliable Web App Pattern for.NET YouTube 影片和文章,以取得從頭建立新式、可靠、效能強、可測試、具成本效益及可調整的 ASP.NET Core 應用程式或重構現有應用程式的指導。
將驗證支援新增至 Web API
ASP.NET Core Identity 會將使用者介面 (UI) 登入功能新增至 ASP.NET Core Web 應用程式。 若要保護 Web API 和 SPA,請使用下列其中一項:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity 伺服器
Duende Identity 伺服器是適用於 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 架構。 Duende Identity 伺服器會啟用下列安全性功能:
- 驗證即服務 (AaaS)
- 多個應用程式類型的單一登入/登出 (SSO)
- API 的存取控制
- Federation Gateway
重要
Duende Software 可能會要求您支付授權費用才能在生產環境中使用 Duende Identity 伺服器。 如需詳細資訊,請參閱從 ASP.NET Core 5.0 移轉至 6.0。
如需詳細資訊,請參閱 Duende Identity 伺服器文件 (Duende Software 網站)。
發佈至 Azure
如需部署至 Azure 的資訊,請參閱 快速入門:部署 ASP.NET Web 應用程式。
其他資源
檢視或下載本教學課程的範例程式碼。 請參閱如何下載。
如需詳細資訊,請參閱以下資源:
- 使用 ASP.NET Core 建立 Web API
- 教學課程:使用 ASP.NET Core 建立基本 API
- Swagger/OpenAPI 的 ASP.NET Core Web API 文件
- ASP.NET Core 中的 Razor 頁面與 Entity Framework Core 教學課程 - 1/8
- ASP.NET Core 中的路由至控制器動作
- ASP.NET Core Web API 中的控制器動作傳回類型
- 將 ASP.NET Core 應用程式部署至 Azure App Service
- 裝載及部署 ASP.NET Core
- 使用 ASP.NET Core 建立 Web API
本教學課程將教導建置使用資料庫之控制器型 Web API 的基本概念。 在 ASP.NET Core 中建立 API 的另一種方法是建立最小的 API。 如需在基本 API 與控制器型 API 之間選擇的說明,請參閱 API 概觀。 如需建立最小 API 的教學課程,請參閱教學課程:使用 ASP.NET Core 建立最小 API。
概觀
本教學課程會建立以下 API:
API | 描述 | 要求本文 | 回應本文 |
---|---|---|---|
GET /api/todoitems |
取得所有待辦事項 | 無 | 待辦事項的陣列 |
GET /api/todoitems/{id} |
依識別碼取得項目 | 無 | 待辦事項 |
POST /api/todoitems |
新增記錄 | 待辦事項 | 待辦事項 |
PUT /api/todoitems/{id} |
更新現有的項目 | 待辦事項 | 無 |
DELETE /api/todoitems/{id} |
刪除項目 | 無 | 無 |
下圖顯示應用程式的設計。
必要條件
Visual Studio 2022 和 ASP.NET 與 Web 開發工作負載。
建立 Web 專案
- 從 [檔案] 功能表選取 [新增] >[專案] 。
- 在搜尋方塊中輸入 Web API。
- 選取 ASP.NET Core Web API 範本,然後選取 [下一步]。
- 在 [設定新專案] 對話方塊中,將專案命名為 TodoApi,然後選取 [下一步]。
- 在 [其他資訊] 對話方塊中:
- 確認 Framework 為 .NET 8.0 (長期支援)。
- 確認已核取 [使用控制器 (取消核取以使用最小 API)] 核取方塊。
- 確認已核取 [啟用 OpenAPI 支援] 核取方塊。
- 選取建立。
新增 NuGet 套件
必須新增 NuGet 套件,才能支援本教學課程中使用的資料庫。
- 在 [工具] 功能表上,選取 [NuGet 套件管理員] > [管理解決方案的 NuGet 套件]。
- 選取 [瀏覽] 索引標籤。
- 在搜尋方塊中輸入 Microsoft.EntityFrameworkCore.InMemory,然後選取
Microsoft.EntityFrameworkCore.InMemory
。 - 選取右窗格中的 [專案] 核取方塊,然後選取 [安裝]。
注意
如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件) 的安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。
測試專案
專案範本會建立支援 Swagger 的 WeatherForecast
API。
按 Ctrl+F5 即可執行而不使用偵錯工具。
當專案尚未設定為使用 SSL 時,Visual Studio 會顯示下列對話方塊:
如果您信任 IIS Express SSL 憑證,請選取 [是]。
此時會顯示下列對話方塊:
若您同意信任開發憑證,請選取 [是]。
如需關於信任 Firefox 瀏覽器的資訊,請參閱 Firefox SEC_ERROR_INADEQUATE_KEY_USAGE 憑證錯誤。
Visual Studio 會啟動預設瀏覽器並瀏覽至 https://localhost:<port>/swagger/index.html
,其中 <port>
是專案建立時設定的隨機選擇連接埠號碼。
Swagger 頁面 /swagger/index.html
隨即顯示。 選取 [GET]>[試用]>[執行]。 頁面會顯示:
- 用來測試 WeatherForecast API 的 Curl 命令。
- 用來測試 WeatherForecast API 的 URL。
- 回應碼、本文和標頭。
- 具有媒體類型與範例值和架構的下拉式清單方塊。
如果 Swagger 頁面未出現,請參閱這個 GitHub 問題。
Swagger 可用來為 Web API 產生有用的文件和說明頁面。 本教學課程會使用 Swagger 來測試應用程式。 如需 Swagger 的詳細資訊,請參閱使用 ASP.NET Core Web API 文件搭配 Swagger / OpenAPI。
複製並貼上瀏覽器中的要求 URL:https://localhost:<port>/weatherforecast
系統會傳回類似下列範例的 JSON:
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
新增模型類別
「模型」是代表應用程式所管理資料的一組類別。 此應用程式的模型是 TodoItem
類別。
- 在 [方案總管] 中,以滑鼠右鍵按一下專案。 選取 [新增]>[新增資料夾]。 將資料夾命名為
Models
註冊免費試用帳戶。 - 以滑鼠右鍵按一下
Models
資料夾並選取 [新增]>[類別]。 將類別命名為 TodoItem,然後選取 [新增]。 - 以下列項目取代範本程式碼:
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 類別來建立。
- 以滑鼠右鍵按一下
Models
資料夾並選取 [新增]>[類別]。 將類別命名為 TodoContext,然後按一下 [新增]。
輸入下列程式碼:
using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } = null!; }
登錄資料庫內容
在 ASP.NET Core 中,資料庫內容等服務必須向相依性插入 (DI) 容器註冊。 此容器會將服務提供給控制器。
使用下列醒目提示的程式碼更新 Program.cs
:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
上述 程式碼:
- 加入
using
指示詞。 - 將資料庫內容新增至 DI 容器。
- 指定資料庫內容將會使用記憶體內部資料庫。
Scaffold 控制器
以滑鼠右鍵按一下
Controllers
資料夾。選取 [新增]。
選取 [使用 Entity Framework 執行動作的 API 控制器],然後選取 [新增]。
在 [使用 Entity Framework 執行動作的 API 控制器] 對話方塊中:
- 在 [模型類別] 中選取 [TodoItem (TodoApi.Models)]。
- 在 [資料內容類別] 中選取 [TodoContext (TodoApi.Models)]。
- 選取新增。
如果 Scaffolding 作業失敗,請選取 [新增] 以嘗試第二次 Scaffolding。
產生的程式碼:
- 使用
[ApiController]
屬性標記類別。 這個屬性表示控制器會回應 Web API 要求。 如需屬性啟用的特定行為相關資訊,請參閱 使用 ASP.NET Core 建立 Web API。 - 使用 DI 將資料庫內容 (
TodoContext
) 插入到控制器中。 控制器中的每一個 CRUD 方法都會使用資料庫內容。
ASP.NET Core 範本適用於:
- 路由範本中檢視包含
[action]
的控制器。 - API 控制器在路由範本中不包含
[action]
。
當 [action]
權杖不在路由範本中時,動作名稱 (方法名稱) 不會包含在端點中。 也就是說,動作的相關聯方法名稱不會用於比對路由。
更新 PostTodoItem 建立方法
更新 PostTodoItem
中的 return 陳述式,以使用 nameof 運算子:
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}
上述程式碼是 HTTP POST
方法,以 [HttpPost]
屬性表示。 該方法會從 HTTP 要求本文取得 TodoItem
的值。
如需詳細資訊,請參閱使用 Http[Verb] 屬性的屬性路由。
CreatedAtAction 方法:
- 成功時會傳回 HTTP 201 狀態碼。 對於可在伺服器上建立新資源的
HTTP POST
方法,HTTP 201
是標準回應。 - 將 Location標頭新增到回應。
Location
標頭會指定新建待辦事項的 URI。 如需詳細資訊,請參閱 10.2.2 201 Created (已建立 10.2.2 201)。 - 參考
GetTodoItem
動作以建立Location
標頭的 URI。 C#nameof
關鍵字是用來避免在CreatedAtAction
呼叫中以硬式編碼方式寫入動作名稱。
測試 PostTodoItem
按 Ctrl+F5 執行應用程式。
在 Swagger 瀏覽器視窗中,選取 [POST /api/TodoItems],然後選取 [試用]。
在要求本文輸入視窗中,更新 JSON。 例如,
{ "name": "walk dog", "isComplete": true }
選取 [執行]
測試位置標頭 URI
在上述 POST 中,Swagger UI 會顯示 [回應] 標頭底下的位置標頭。 例如: location: https://localhost:7260/api/TodoItems/1
。 位置標頭會顯示所建立資源的 URI。
若要測試位置標頭:
在 Swagger 瀏覽器視窗中,選取 [GET /api/TodoItems/{id}],然後選取 [試用]。
在
id
輸入方塊中輸入1
,然後選取 [執行]。
檢查 GET 方法
兩個 GET 端點即會實作:
GET /api/todoitems
GET /api/todoitems/{id}
上一節顯示 /api/todoitems/{id}
路由的範例。
依照 POST 指示新增另一個待辦事項,然後使用 Swagger 測試 /api/todoitems
路由。
這個應用程式會使用記憶體內部資料庫。 如果應用程式在停止後再啟動,上述 GET 要求不會傳回任何資料。 如果沒有傳回任何資料,請將資料 POST 到應用程式。
傳送和 URL 路徑
[HttpGet]
屬性代表回應 HTTP GET
要求的方法。 每個方法的 URL 路徑的建構方式如下:
一開始在控制器的
Route
屬性中使用範本字串:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase
以控制器的名稱取代
[controller]
,也就是將控制器類別名稱減去 "Controller" 字尾。 在此範例中,控制器類別名稱是 TodoItemsController,因此控制器名稱是 "TodoItems"。 ASP.NET Core 路由不區分大小寫。如果
[HttpGet]
屬性具有路由範本 (例如[HttpGet("products")]
),請將其附加到路徑。 此範例不使用範本。 如需詳細資訊,請參閱使用 Http[Verb] 屬性的屬性路由。
在下列 GetTodoItem
方法中,"{id}"
是待辦事項唯一識別碼的預留位置變數。 在叫用 GetTodoItem
時,會將 URL 中的 "{id}"
值提供給方法的 id
參數。
[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 OK,假設沒有任何未處理的例外狀況。 未處理的例外狀況會轉譯成 5xx 錯誤。
ActionResult
傳回型別可代表各種 HTTP 狀態碼。 例如,GetTodoItem
可傳回兩個不同的狀態值:
PutTodoItem 方法
檢查 PutTodoItem
方法:
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
PutTodoItem
類似於 PostTodoItem
,但是會使用 HTTP PUT
。 回應是 204 (No Content) (204 (沒有內容))。 根據 HTTP 規格,PUT
要求需要用戶端傳送整個更新的實體,而不只是變更。 若要支援部分更新,請使用 HTTP PATCH。
測試 PutTodoItem 方法
此範例使用在每次應用程式啟動都必須初始化的記憶體內部資料庫。 資料庫中必須有項目,您才能進行 PUT 呼叫。 在發出 PUT 呼叫之前,呼叫 GET 以確保資料庫中有項目。
使用 Swagger UI,使用 PUT 按鈕來更新識別碼為 1 的 TodoItem
,並將其名稱設定為 "feed fish"
。 請注意,回應為 HTTP 204 No Content
。
DeleteTodoItem 方法
檢查 DeleteTodoItem
方法:
[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 方法
使用 Swagger UI 刪除識別碼為 1 的 TodoItem
。 請注意,回應為 HTTP 204 No Content
。
使用其他工具進行測試
還有其他許多工具可用來測試 Web API,例如:
- Visual Studio 端點總管和 .http 檔案
- http-repl
- curl。 Swagger 會使用
curl
並顯示其提交的curl
命令。 - Fiddler
如需詳細資訊,請參閱
防止過度張貼
目前範例應用程式會公開整個 TodoItem
物件。 生產應用程式通常會限制輸入的資料,並使用模型的子集傳回。 背後有多個原因,而安全性是主要原因。 模型的子集通常稱為資料傳輸物件 (DTO)、輸入模型或檢視模型。 本教學課程中使用 DTO。
DTO 可用來:
- 防止過度張貼。
- 隱藏用戶端不應該檢視的屬性。
- 省略一些屬性,以減少承載大小。
- 包含巢狀物件的壓平合併物件圖形。 壓平合併物件圖形對用戶端會更方便。
若要示範 DTO 方法,請更新 TodoItem
類別以包含祕密欄位:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
}
祕密欄位必須從此應用程式隱藏,但系統管理應用程式可以選擇公開它。
確認您可以張貼並取得祕密欄位。
建立 DTO 模型:
namespace TodoApi.Models;
public class TodoItemDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
更新 TodoItemsController
以使用 TodoItemDTO
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
// GET: api/TodoItems/5
// <snippet_GetByID>
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
// </snippet_GetByID>
// PUT: api/TodoItems/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Update>
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
{
if (id != todoDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoDTO.Name;
todoItem.IsComplete = todoDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// </snippet_Update>
// POST: api/TodoItems
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Create>
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoDTO.IsComplete,
Name = todoDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// </snippet_Create>
// DELETE: api/TodoItems/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();
}
private bool TodoItemExists(long id)
{
return _context.TodoItems.Any(e => e.Id == id);
}
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
new TodoItemDTO
{
Id = todoItem.Id,
Name = todoItem.Name,
IsComplete = todoItem.IsComplete
};
}
確認您無法張貼或取得祕密欄位。
使用 JavaScript 呼叫 Web API
請參閱教學課程:使用 JavaScript 呼叫 ASP.NET Core Web API。
Web API 影片系列
請參閱影片:初學者系列:Web API。
可靠的 Web 應用程式模式
請參閱 The Reliable Web App Pattern for.NET YouTube 影片和文章,以取得從頭建立新式、可靠、效能強、可測試、具成本效益及可調整的 ASP.NET Core 應用程式或重構現有應用程式的指導。
將驗證支援新增至 Web API
ASP.NET Core Identity 會將使用者介面 (UI) 登入功能新增至 ASP.NET Core Web 應用程式。 若要保護 Web API 和 SPA,請使用下列其中一項:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity 伺服器
Duende Identity 伺服器是適用於 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 架構。 Duende Identity 伺服器會啟用下列安全性功能:
- 驗證即服務 (AaaS)
- 多個應用程式類型的單一登入/登出 (SSO)
- API 的存取控制
- Federation Gateway
重要
Duende Software 可能會要求您支付授權費用才能在生產環境中使用 Duende Identity 伺服器。 如需詳細資訊,請參閱從 ASP.NET Core 5.0 移轉至 6.0。
如需詳細資訊,請參閱 Duende Identity 伺服器文件 (Duende Software 網站)。
發佈至 Azure
如需部署至 Azure 的資訊,請參閱 快速入門:部署 ASP.NET Web 應用程式。
其他資源
檢視或下載本教學課程的範例程式碼。 請參閱如何下載。
如需詳細資訊,請參閱以下資源:
- 使用 ASP.NET Core 建立 Web API
- 教學課程:使用 ASP.NET Core 建立基本 API
- Swagger/OpenAPI 的 ASP.NET Core Web API 文件
- ASP.NET Core 中的 Razor 頁面與 Entity Framework Core 教學課程 - 1/8
- ASP.NET Core 中的路由至控制器動作
- ASP.NET Core Web API 中的控制器動作傳回類型
- 將 ASP.NET Core 應用程式部署至 Azure App Service
- 裝載及部署 ASP.NET Core
- 使用 ASP.NET Core 建立 Web API
本教學課程將教導建置使用資料庫之控制器型 Web API 的基本概念。 在 ASP.NET Core 中建立 API 的另一種方法是建立最小的 API。 如需在基本 API 與控制器型 API 之間選擇的說明,請參閱 API 概觀。 如需建立最小 API 的教學課程,請參閱教學課程:使用 ASP.NET Core 建立最小 API。
概觀
本教學課程會建立以下 API:
API | 描述 | 要求本文 | 回應本文 |
---|---|---|---|
GET /api/todoitems |
取得所有待辦事項 | 無 | 待辦事項的陣列 |
GET /api/todoitems/{id} |
依識別碼取得項目 | 無 | 待辦事項 |
POST /api/todoitems |
新增記錄 | 待辦事項 | 待辦事項 |
PUT /api/todoitems/{id} |
更新現有的項目 | 待辦事項 | 無 |
DELETE /api/todoitems/{id} |
刪除項目 | 無 | 無 |
下圖顯示應用程式的設計。
必要條件
Visual Studio 2022 和 ASP.NET 與 Web 開發工作負載。
建立 Web 專案
- 從 [檔案] 功能表選取 [新增] >[專案] 。
- 在搜尋方塊中輸入 Web API。
- 選取 ASP.NET Core Web API 範本,然後選取 [下一步]。
- 在 [設定新專案] 對話方塊中,將專案命名為 TodoApi,然後選取 [下一步]。
- 在 [其他資訊] 對話方塊中:
- 確認 Framework 為 .NET 8.0 (長期支援)。
- 確認已核取 [使用控制器 (取消核取以使用最小 API)] 核取方塊。
- 確認已核取 [啟用 OpenAPI 支援] 核取方塊。
- 選取建立。
新增 NuGet 套件
必須新增 NuGet 套件,才能支援本教學課程中使用的資料庫。
- 在 [工具] 功能表上,選取 [NuGet 套件管理員] > [管理解決方案的 NuGet 套件]。
- 選取 [瀏覽] 索引標籤。
- 在搜尋方塊中輸入 Microsoft.EntityFrameworkCore.InMemory,然後選取
Microsoft.EntityFrameworkCore.InMemory
。 - 選取右窗格中的 [專案] 核取方塊,然後選取 [安裝]。
注意
如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件) 的安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。
測試專案
專案範本會建立支援 Swagger 的 WeatherForecast
API。
按 Ctrl+F5 即可執行而不使用偵錯工具。
當專案尚未設定為使用 SSL 時,Visual Studio 會顯示下列對話方塊:
如果您信任 IIS Express SSL 憑證,請選取 [是]。
此時會顯示下列對話方塊:
若您同意信任開發憑證,請選取 [是]。
如需關於信任 Firefox 瀏覽器的資訊,請參閱 Firefox SEC_ERROR_INADEQUATE_KEY_USAGE 憑證錯誤。
Visual Studio 會啟動預設瀏覽器並瀏覽至 https://localhost:<port>/swagger/index.html
,其中 <port>
是專案建立時設定的隨機選擇連接埠號碼。
Swagger 頁面 /swagger/index.html
隨即顯示。 選取 [GET]>[試用]>[執行]。 頁面會顯示:
- 用來測試 WeatherForecast API 的 Curl 命令。
- 用來測試 WeatherForecast API 的 URL。
- 回應碼、本文和標頭。
- 具有媒體類型與範例值和架構的下拉式清單方塊。
如果 Swagger 頁面未出現,請參閱這個 GitHub 問題。
Swagger 可用來為 Web API 產生有用的文件和說明頁面。 本教學課程會使用 Swagger 來測試應用程式。 如需 Swagger 的詳細資訊,請參閱使用 ASP.NET Core Web API 文件搭配 Swagger / OpenAPI。
複製並貼上瀏覽器中的要求 URL:https://localhost:<port>/weatherforecast
系統會傳回類似下列範例的 JSON:
[
{
"date": "2019-07-16T19:04:05.7257911-06:00",
"temperatureC": 52,
"temperatureF": 125,
"summary": "Mild"
},
{
"date": "2019-07-17T19:04:05.7258461-06:00",
"temperatureC": 36,
"temperatureF": 96,
"summary": "Warm"
},
{
"date": "2019-07-18T19:04:05.7258467-06:00",
"temperatureC": 39,
"temperatureF": 102,
"summary": "Cool"
},
{
"date": "2019-07-19T19:04:05.7258471-06:00",
"temperatureC": 10,
"temperatureF": 49,
"summary": "Bracing"
},
{
"date": "2019-07-20T19:04:05.7258474-06:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Chilly"
}
]
新增模型類別
「模型」是代表應用程式所管理資料的一組類別。 此應用程式的模型是 TodoItem
類別。
- 在 [方案總管] 中,以滑鼠右鍵按一下專案。 選取 [新增]>[新增資料夾]。 將資料夾命名為
Models
註冊免費試用帳戶。 - 以滑鼠右鍵按一下
Models
資料夾並選取 [新增]>[類別]。 將類別命名為 TodoItem,然後選取 [新增]。 - 以下列項目取代範本程式碼:
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 類別來建立。
- 以滑鼠右鍵按一下
Models
資料夾並選取 [新增]>[類別]。 將類別命名為 TodoContext,然後按一下 [新增]。
輸入下列程式碼:
using Microsoft.EntityFrameworkCore; namespace TodoApi.Models; public class TodoContext : DbContext { public TodoContext(DbContextOptions<TodoContext> options) : base(options) { } public DbSet<TodoItem> TodoItems { get; set; } = null!; }
登錄資料庫內容
在 ASP.NET Core 中,資料庫內容等服務必須向相依性插入 (DI) 容器註冊。 此容器會將服務提供給控制器。
使用下列醒目提示的程式碼更新 Program.cs
:
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddDbContext<TodoContext>(opt =>
opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
上述 程式碼:
- 加入
using
指示詞。 - 將資料庫內容新增至 DI 容器。
- 指定資料庫內容將會使用記憶體內部資料庫。
Scaffold 控制器
以滑鼠右鍵按一下
Controllers
資料夾。選取 [新增]。
選取 [使用 Entity Framework 執行動作的 API 控制器],然後選取 [新增]。
在 [使用 Entity Framework 執行動作的 API 控制器] 對話方塊中:
- 在 [模型類別] 中選取 [TodoItem (TodoApi.Models)]。
- 在 [資料內容類別] 中選取 [TodoContext (TodoApi.Models)]。
- 選取新增。
如果 Scaffolding 作業失敗,請選取 [新增] 以嘗試第二次 Scaffolding。
產生的程式碼:
- 使用
[ApiController]
屬性標記類別。 這個屬性表示控制器會回應 Web API 要求。 如需屬性啟用的特定行為相關資訊,請參閱 使用 ASP.NET Core 建立 Web API。 - 使用 DI 將資料庫內容 (
TodoContext
) 插入到控制器中。 控制器中的每一個 CRUD 方法都會使用資料庫內容。
ASP.NET Core 範本適用於:
- 路由範本中檢視包含
[action]
的控制器。 - API 控制器在路由範本中不包含
[action]
。
當 [action]
權杖不在路由範本中時,動作名稱 (方法名稱) 不會包含在端點中。 也就是說,動作的相關聯方法名稱不會用於比對路由。
更新 PostTodoItem 建立方法
更新 PostTodoItem
中的 return 陳述式,以使用 nameof 運算子:
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
// return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}
上述程式碼是 HTTP POST
方法,以 [HttpPost]
屬性表示。 該方法會從 HTTP 要求本文取得 TodoItem
的值。
如需詳細資訊,請參閱使用 Http[Verb] 屬性的屬性路由。
CreatedAtAction 方法:
- 成功時會傳回 HTTP 201 狀態碼。 對於可在伺服器上建立新資源的
HTTP POST
方法,HTTP 201
是標準回應。 - 將 Location標頭新增到回應。
Location
標頭會指定新建待辦事項的 URI。 如需詳細資訊,請參閱 10.2.2 201 Created (已建立 10.2.2 201)。 - 參考
GetTodoItem
動作以建立Location
標頭的 URI。 C#nameof
關鍵字是用來避免在CreatedAtAction
呼叫中以硬式編碼方式寫入動作名稱。
測試 PostTodoItem
按 Ctrl+F5 執行應用程式。
在 Swagger 瀏覽器視窗中,選取 [POST /api/TodoItems],然後選取 [試用]。
在要求本文輸入視窗中,更新 JSON。 例如,
{ "name": "walk dog", "isComplete": true }
選取 [執行]
測試位置標頭 URI
在上述 POST 中,Swagger UI 會顯示 [回應] 標頭底下的位置標頭。 例如: location: https://localhost:7260/api/TodoItems/1
。 位置標頭會顯示所建立資源的 URI。
若要測試位置標頭:
在 Swagger 瀏覽器視窗中,選取 [GET /api/TodoItems/{id}],然後選取 [試用]。
在
id
輸入方塊中輸入1
,然後選取 [執行]。
檢查 GET 方法
兩個 GET 端點即會實作:
GET /api/todoitems
GET /api/todoitems/{id}
上一節顯示 /api/todoitems/{id}
路由的範例。
依照 POST 指示新增另一個待辦事項,然後使用 Swagger 測試 /api/todoitems
路由。
這個應用程式會使用記憶體內部資料庫。 如果應用程式在停止後再啟動,上述 GET 要求不會傳回任何資料。 如果沒有傳回任何資料,請將資料 POST 到應用程式。
傳送和 URL 路徑
[HttpGet]
屬性代表回應 HTTP GET
要求的方法。 每個方法的 URL 路徑的建構方式如下:
一開始在控制器的
Route
屬性中使用範本字串:[Route("api/[controller]")] [ApiController] public class TodoItemsController : ControllerBase
以控制器的名稱取代
[controller]
,也就是將控制器類別名稱減去 "Controller" 字尾。 在此範例中,控制器類別名稱是 TodoItemsController,因此控制器名稱是 "TodoItems"。 ASP.NET Core 路由不區分大小寫。如果
[HttpGet]
屬性具有路由範本 (例如[HttpGet("products")]
),請將其附加到路徑。 此範例不使用範本。 如需詳細資訊,請參閱使用 Http[Verb] 屬性的屬性路由。
在下列 GetTodoItem
方法中,"{id}"
是待辦事項唯一識別碼的預留位置變數。 在叫用 GetTodoItem
時,會將 URL 中的 "{id}"
值提供給方法的 id
參數。
[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 OK,假設沒有任何未處理的例外狀況。 未處理的例外狀況會轉譯成 5xx 錯誤。
ActionResult
傳回型別可代表各種 HTTP 狀態碼。 例如,GetTodoItem
可傳回兩個不同的狀態值:
PutTodoItem 方法
檢查 PutTodoItem
方法:
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
PutTodoItem
類似於 PostTodoItem
,但是會使用 HTTP PUT
。 回應是 204 (No Content) (204 (沒有內容))。 根據 HTTP 規格,PUT
要求需要用戶端傳送整個更新的實體,而不只是變更。 若要支援部分更新,請使用 HTTP PATCH。
測試 PutTodoItem 方法
此範例使用在每次應用程式啟動都必須初始化的記憶體內部資料庫。 資料庫中必須有項目,您才能進行 PUT 呼叫。 在發出 PUT 呼叫之前,呼叫 GET 以確保資料庫中有項目。
使用 Swagger UI,使用 PUT 按鈕來更新識別碼為 1 的 TodoItem
,並將其名稱設定為 "feed fish"
。 請注意,回應為 HTTP 204 No Content
。
DeleteTodoItem 方法
檢查 DeleteTodoItem
方法:
[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 方法
使用 Swagger UI 刪除識別碼為 1 的 TodoItem
。 請注意,回應為 HTTP 204 No Content
。
使用其他工具進行測試
還有其他許多工具可用來測試 Web API,例如:
- Visual Studio 端點總管和 .http 檔案
- http-repl
- curl。 Swagger 會使用
curl
並顯示其提交的curl
命令。 - Fiddler
如需詳細資訊,請參閱
防止過度張貼
目前範例應用程式會公開整個 TodoItem
物件。 生產應用程式通常會限制輸入的資料,並使用模型的子集傳回。 背後有多個原因,而安全性是主要原因。 模型的子集通常稱為資料傳輸物件 (DTO)、輸入模型或檢視模型。 本教學課程中使用 DTO。
DTO 可用來:
- 防止過度張貼。
- 隱藏用戶端不應該檢視的屬性。
- 省略一些屬性,以減少承載大小。
- 包含巢狀物件的壓平合併物件圖形。 壓平合併物件圖形對用戶端會更方便。
若要示範 DTO 方法,請更新 TodoItem
類別以包含祕密欄位:
namespace TodoApi.Models
{
public class TodoItem
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
public string? Secret { get; set; }
}
}
祕密欄位必須從此應用程式隱藏,但系統管理應用程式可以選擇公開它。
確認您可以張貼並取得祕密欄位。
建立 DTO 模型:
namespace TodoApi.Models;
public class TodoItemDTO
{
public long Id { get; set; }
public string? Name { get; set; }
public bool IsComplete { get; set; }
}
更新 TodoItemsController
以使用 TodoItemDTO
:
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace TodoApi.Controllers;
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
{
private readonly TodoContext _context;
public TodoItemsController(TodoContext context)
{
_context = context;
}
// GET: api/TodoItems
[HttpGet]
public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
{
return await _context.TodoItems
.Select(x => ItemToDTO(x))
.ToListAsync();
}
// GET: api/TodoItems/5
// <snippet_GetByID>
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
return ItemToDTO(todoItem);
}
// </snippet_GetByID>
// PUT: api/TodoItems/5
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Update>
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItemDTO todoDTO)
{
if (id != todoDTO.Id)
{
return BadRequest();
}
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
return NotFound();
}
todoItem.Name = todoDTO.Name;
todoItem.IsComplete = todoDTO.IsComplete;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
// </snippet_Update>
// POST: api/TodoItems
// To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
// <snippet_Create>
[HttpPost]
public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoDTO)
{
var todoItem = new TodoItem
{
IsComplete = todoDTO.IsComplete,
Name = todoDTO.Name
};
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
return CreatedAtAction(
nameof(GetTodoItem),
new { id = todoItem.Id },
ItemToDTO(todoItem));
}
// </snippet_Create>
// DELETE: api/TodoItems/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();
}
private bool TodoItemExists(long id)
{
return _context.TodoItems.Any(e => e.Id == id);
}
private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
new TodoItemDTO
{
Id = todoItem.Id,
Name = todoItem.Name,
IsComplete = todoItem.IsComplete
};
}
確認您無法張貼或取得祕密欄位。
使用 JavaScript 呼叫 Web API
請參閱教學課程:使用 JavaScript 呼叫 ASP.NET Core Web API。
Web API 影片系列
請參閱影片:初學者系列:Web API。
可靠的 Web 應用程式模式
請參閱 The Reliable Web App Pattern for.NET YouTube 影片和文章,以取得從頭建立新式、可靠、效能強、可測試、具成本效益及可調整的 ASP.NET Core 應用程式或重構現有應用程式的指導。
將驗證支援新增至 Web API
ASP.NET Core Identity 會將使用者介面 (UI) 登入功能新增至 ASP.NET Core Web 應用程式。 若要保護 Web API 和 SPA,請使用下列其中一項:
- Microsoft Entra ID
- Azure Active Directory B2C (Azure AD B2C)
- Duende Identity 伺服器
Duende Identity 伺服器是適用於 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 架構。 Duende Identity 伺服器會啟用下列安全性功能:
- 驗證即服務 (AaaS)
- 多個應用程式類型的單一登入/登出 (SSO)
- API 的存取控制
- Federation Gateway
重要
Duende Software 可能會要求您支付授權費用才能在生產環境中使用 Duende Identity 伺服器。 如需詳細資訊,請參閱從 ASP.NET Core 5.0 移轉至 6.0。
如需詳細資訊,請參閱 Duende Identity 伺服器文件 (Duende Software 網站)。
發佈至 Azure
如需部署至 Azure 的資訊,請參閱 快速入門:部署 ASP.NET Web 應用程式。
其他資源
檢視或下載本教學課程的範例程式碼。 請參閱如何下載。
如需詳細資訊,請參閱以下資源:
- 使用 ASP.NET Core 建立 Web API
- 教學課程:使用 ASP.NET Core 建立基本 API
- Swagger/OpenAPI 的 ASP.NET Core Web API 文件
- ASP.NET Core 中的 Razor 頁面與 Entity Framework Core 教學課程 - 1/8
- ASP.NET Core 中的路由至控制器動作
- ASP.NET Core Web API 中的控制器動作傳回類型
- 將 ASP.NET Core 應用程式部署至 Azure App Service
- 裝載及部署 ASP.NET Core
- 使用 ASP.NET Core 建立 Web API