備註
這不是本文的最新版本。 關於目前版本,請參閱 本文的 .NET 10 版本。
警告
此版本的 ASP.NET Core 已不再受支援。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援政策。 如需目前的版本,請參閱 本文的 .NET 9 版本。
本文說明如何處理 ASP.NET 核心 API 中的錯誤。 已選取 [最小 API] 的檔案。 若要查看控制器型 API 的文件,請選取 [控制器] 索引標籤。如需 Blazor 錯誤處理指引,請參閱 處理 ASP.NET Core Blazor 應用程式中的錯誤。
開發人員例外頁面
開發人員例外狀況頁面會顯示未處理要求例外狀況的詳細資訊。 它用來 DeveloperExceptionPageMiddleware 從 HTTP 管線擷取同步和非同步例外狀況,並產生錯誤回應。 開發人員例外狀況頁面會在中介軟體管線的早期執行,因此它可以攔截後面的中介軟體中擲回的未處理例外狀況。
ASP.NET Core 應用程式預設會在下列情況下啟用開發人員例外頁面:
- 在 開發環境中執行。
- 應用程式是使用目前的範本建立的,也就是使用 WebApplication.CreateBuilder。
使用舊版範本建立的應用程式,亦即使用 WebHost.CreateDefaultBuilder,可以透過呼叫 app.UseDeveloperExceptionPage來啟用開發人員例外狀況頁面。
警告
除非 應用程式在開發環境中執行,否則請勿啟用開發人員例外狀況頁面。 當應用程式在生產環境中執行時,請勿公開共用詳細的例外狀況資訊。 如需配置環境的相關資訊,請參閱 ASP.NET Core 執行時期環境。
開發人員例外狀況頁面可以包含例外狀況和要求的下列相關資訊:
- 堆疊追蹤
- 查詢字串參數 (如果有的話)
- Cookies(如有)
- Headers
- 端點中繼資料 (如果有的話)
開發人員例外狀況頁面不保證提供任何資訊。 使用 記錄來 取得完整的錯誤資訊。
下圖顯示範例開發人員例外狀況頁面,其中包含動畫,以顯示索引標籤和顯示的資訊:
為了回應具有標頭的要求 Accept: text/plain ,開發人員例外狀況頁面會傳回純文字,而不是 HTML。 例如:
Status: 500 Internal Server Error
Time: 9.39 msSize: 480 bytes
FormattedRawHeadersRequest
Body
text/plain; charset=utf-8, 480 bytes
System.InvalidOperationException: Sample Exception
at WebApplicationMinimal.Program.<>c.<Main>b__0_0() in C:\Source\WebApplicationMinimal\Program.cs:line 12
at lambda_method1(Closure, Object, HttpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
HEADERS
=======
Accept: text/plain
Host: localhost:7267
traceparent: 00-0eab195ea19d07b90a46cd7d6bf2f
若要在最小 API 中查看開發人員例外狀況頁面:
- 在 開發環境中執行範例應用程式。
- 移至
/exception端點。
本節參考下列範例應用程式,以示範在最小 API 中處理例外狀況的方法。 當請求端點 /exception 時,它會擲回例外狀況:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/exception", () =>
{
throw new InvalidOperationException("Sample Exception");
});
app.MapGet("/", () => "Test by calling /exception");
app.Run();
例外狀況處理常式
在非開發環境中,請使用 「例外狀況處理常式中介軟體 」來產生錯誤承載。
若要設定 Exception Handler Middleware,請呼叫 UseExceptionHandler。 例如,下列程式碼會變更應用程式,以符合 RFC 7807 規範的承載回應用戶端。 如需詳細資訊,請參閱本文稍後的問題 詳細資料 一節。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp
=> exceptionHandlerApp.Run(async context
=> await Results.Problem()
.ExecuteAsync(context)));
app.MapGet("/exception", () =>
{
throw new InvalidOperationException("Sample Exception");
});
app.MapGet("/", () => "Test by calling /exception");
app.Run();
用戶端和伺服器錯誤回應
請考慮下列最小 API 應用程式。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)));
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
/users端點會產生 200 OKjson when User is greater idthan 的0表示法,否則是400 BAD REQUEST沒有回應內文的狀態碼。 如需建立回應的詳細資訊,請參閱在 最小 API 應用程式中建立回應。
可以 Status Code Pages middleware 配置為在 空時為所有 HTTP 用戶端 (400-499) 或伺服器 (500 -599) 回應產生通用內文內容。 中介軟體是藉由呼叫 UseStatusCodePages 延伸模組方法來設定。
舉例來說,下列範例會變更應用程式,以符合 RFC 7807 規範的承載回應用戶端,以回應所有用戶端和伺服器回應,包括路由錯誤 (例如 404 NOT FOUND)。 如需詳細資訊,請參閱 問題詳細資料 一節。
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseStatusCodePages(async statusCodeContext
=> await Results.Problem(statusCode: statusCodeContext.HttpContext.Response.StatusCode)
.ExecuteAsync(statusCodeContext.HttpContext));
app.MapGet("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
問題詳細資料
問題詳細資料 不是描述 HTTP API 錯誤的唯一回應格式,不過,它們通常用來報告 HTTP API 的錯誤。
問題詳細資料服務實作 IProblemDetailsService 介面,支援在 ASP.NET 核心中建立問題詳細資料。
AddProblemDetails(IServiceCollection)上的IServiceCollection擴充方法會註冊預設IProblemDetailsService實作。
在 ASP.NET Core 應用程式中,下列中介軟體會在呼叫時產生問題詳細資料 HTTP 回應AddProblemDetails,除非要求 HTTP 標頭不包含已註冊 (預設值: ) 所支援的內容類型之一:AcceptIProblemDetailsWriterapplication/json
- ExceptionHandlerMiddleware:在未定義自訂處理常式時產生問題詳細資料回應。
- StatusCodePagesMiddleware:依預設會產生問題詳細資料回應。
-
DeveloperExceptionPageMiddleware:當
Accept要求 HTTP 標頭不包含text/html時,在開發中產生問題詳細資料回應。
可以使用擴充方法,將最小 API 應用程式設定為尚未的所有 HTTP 用戶端和伺服器錯誤回應產生問題詳細資料回應。
下列程式碼會設定應用程式以產生問題詳細資料:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
app.MapGet("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)));
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
如需有關使用 AddProblemDetails的詳細資訊,請參閱 問題詳細資料
IProblemDetailsService 後援
在下列程式碼中, httpContext.Response.WriteAsync("Fallback: An error occurred.") 如果 IProblemDetailsService 實作無法產生 ProblemDetails:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async httpContext =>
{
var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
if (pds == null
|| !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
{
// Fallback behavior
await httpContext.Response.WriteAsync("Fallback: An error occurred.");
}
});
});
app.MapGet("/exception", () =>
{
throw new InvalidOperationException("Sample Exception");
});
app.MapGet("/", () => "Test by calling /exception");
app.Run();
上述 程式碼:
- 如果無法
problemDetailsService寫入ProblemDetails,則會寫入帶有後援代碼的錯誤訊息。 例如, Accept 要求標頭 指定不支援的DefaulProblemDetailsWriter媒體類型的端點。 - 使用 異常處理常式中介軟體。
下列範例與上述範例類似,只是它會呼叫 Status Code Pages middleware。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseStatusCodePages(statusCodeHandlerApp =>
{
statusCodeHandlerApp.Run(async httpContext =>
{
var pds = httpContext.RequestServices.GetService<IProblemDetailsService>();
if (pds == null
|| !await pds.TryWriteAsync(new() { HttpContext = httpContext }))
{
// Fallback behavior
await httpContext.Response.WriteAsync("Fallback: An error occurred.");
}
});
});
app.MapGet("/users/{id:int}", (int id) =>
{
return id <= 0 ? Results.BadRequest() : Results.Ok(new User(id));
});
app.MapGet("/", () => "Test by calling /users/{id:int}");
app.Run();
public record User(int Id);
其他錯誤處理功能
從控制器移轉至最小API
如果您要從控制器型 API 移轉至最小 API:
- 將動作篩選器取代為端點篩選器或中介軟體
- 將模型驗證取代為手動驗證或自訂繫結
- 將異常篩選器取代為異常處理中介軟體
- 設定問題詳細資料,以
AddProblemDetails()取得一致的錯誤回應
何時使用控制器型錯誤處理
如果您需要,請考慮以控制器為基礎的 API:
- 複雜的模型驗證案例
- 跨多個控制器的集中式異常處理
- 對錯誤回應格式的精細控制
- 與篩選器和約定等 MVC 功能整合
如需控制器型錯誤處理的詳細資訊,包括驗證錯誤、問題詳細資料自訂和異常狀況篩選器, 請參閱控制器索引 標籤區段。