處理 ASP.NET Core 中的錯誤
作者:Tom Dykstra
本文涵蓋處理 ASP.NET Core Web 應用程式中錯誤的常見方法。 請參閱處理 web API ASP.NET Core Web API 中的錯誤。
開發人員例外頁面
開發人員 例外狀況頁面 會顯示未處理之要求例外狀況的詳細資訊。 ASP.NET Core應用程式預設會在兩者都啟用開發人員例外狀況頁面:
- 在 開發環境中執行。
- 使用目前範本建立的應用程式,也就是使用 WebApplication.CreateBuilder。 使用
WebHost.CreateDefaultBuilder
建立的應用程式必須在 中Configure
呼叫app.UseDeveloperExceptionPage
來啟用開發人員例外狀況頁面。
開發人員例外狀況頁面會在中介軟體管線中提早執行,以便攔截後續中介軟體中擲回的未處理的例外狀況。
當應用程式在生產環境中執行時,不應公開顯示詳細的例外狀況資訊。 如需設定環境的詳細資訊,請參閱在 ASP.NET Core中使用多個環境。
開發人員例外狀況頁面可以包含有關例外狀況和要求的下列資訊:
- 堆疊追蹤
- 查詢字串參數,如果有的話
- Cookies,如果有的話
- 標題
開發人員例外狀況頁面不保證會提供任何資訊。 使用 記錄 來取得完整的錯誤資訊。
例外處理常式頁面
若要設定 生產環境的自訂錯誤處理頁面,請呼叫 UseExceptionHandler 。 此例外狀況處理中介軟體:
- 攔截和記錄未處理的例外狀況。
- 使用指示的路徑,在替代管線中重新執行要求。 如果回應已啟動,就不會重新執行要求。 範本產生的程式碼會使用
/Error
路徑重新執行要求。
警告
如果替代管線擲回自己的例外狀況,例外狀況處理中介軟體會重新擲回原始例外狀況。
由於此中介軟體可以重新執行要求管線:
- 中介軟體必須使用相同的要求來處理重新進入。 這通常表示在呼叫
_next
或快HttpContext
取其處理之後清除其狀態,以避免重做。 處理要求本文時,這表示緩衝處理或快取表單讀取器之類的結果。 - UseExceptionHandler(IApplicationBuilder, String)針對範本中使用的多載,只會修改要求路徑,並清除路由資料。 標頭、方法和專案等要求資料會依原樣重複使用。
- 範圍服務維持不變。
在下列範例中, UseExceptionHandler 會在非開發環境中新增例外狀況處理中介軟體:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Pages Razor 應用程式範本會在Pages資料夾中提供錯誤頁面 (.cshtml
) 和 PageModel 類別 (ErrorModel
) 。 針對 MVC 應用程式,專案範本包含 Error
動作方法和控制器的錯誤 Home 檢視。
例外狀況處理中介軟體會使用 原始 HTTP 方法重新執行要求。 如果錯誤處理常式端點僅限於一組特定的 HTTP 方法,它只會針對這些 HTTP 方法執行。 例如,使用 屬性的 [HttpGet]
MVC 控制器動作只會針對 GET 要求執行。 為了確保 所有 要求都到達自訂錯誤處理頁面,請勿將它們限制為一組特定的 HTTP 方法。
若要根據原始 HTTP 方法以不同的方式處理例外狀況:
- 針對 Razor Pages,建立多個處理常式方法。 例如,使用
OnGet
來處理 GET 例外狀況,並使用OnPost
來處理 POST 例外狀況。 - 針對 MVC,將 HTTP 動詞屬性套用至多個動作。 例如,使用
[HttpGet]
來處理 GET 例外狀況,並使用[HttpPost]
來處理 POST 例外狀況。
若要允許未經驗證的使用者檢視自訂錯誤處理頁面,請確定它支援匿名存取。
存取例外狀況
使用 IExceptionHandlerPathFeature 存取錯誤處理常式中的例外狀況和原始要求路徑。 下列範例會使用 IExceptionHandlerPathFeature
來取得擲回之例外狀況的詳細資訊:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string? ExceptionMessage { get; set; }
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
var exceptionHandlerPathFeature =
HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
ExceptionMessage = "The file was not found.";
}
if (exceptionHandlerPathFeature?.Path == "/")
{
ExceptionMessage ??= string.Empty;
ExceptionMessage += " Page: Home.";
}
}
}
警告
請勿提供敏感性的錯誤資訊給用戶端。 提供錯誤有安全性風險。
例外處理常式 Lambda
自訂例外處理常式頁面的替代方法,便是將 Lambda 提供給 UseExceptionHandler。 使用 lambda 可讓您在傳回回應之前存取錯誤。
下列程式碼會使用 Lambda 來處理例外狀況:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
// using static System.Net.Mime.MediaTypeNames;
context.Response.ContentType = Text.Plain;
await context.Response.WriteAsync("An exception was thrown.");
var exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
await context.Response.WriteAsync(" The file was not found.");
}
if (exceptionHandlerPathFeature?.Path == "/")
{
await context.Response.WriteAsync(" Page: Home.");
}
});
});
app.UseHsts();
}
警告
請勿提供敏感性的錯誤資訊給用戶端。 提供錯誤有安全性風險。
UseStatusCodePages
根據預設,ASP.NET Core應用程式不會提供 HTTP 錯誤狀態碼的狀態字碼頁面,例如404 - 找不到。 當應用程式設定沒有主體的 HTTP 400-599 錯誤狀態碼時,它會傳回狀態碼和空的回應本文。 若要啟用常見錯誤狀態碼的預設純文字處理常式,請在 中 Program.cs
呼叫 UseStatusCodePages :
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
在要求處理中介軟體之前呼叫 UseStatusCodePages
。 例如,在靜態檔案中介軟體和端點中介軟體之前呼叫 UseStatusCodePages
。
未使用 時 UseStatusCodePages
,流覽至沒有端點的 URL 會傳回瀏覽器相依的錯誤訊息,指出找不到端點。 呼叫 時 UseStatusCodePages
,瀏覽器會傳回下列回應:
Status Code: 404; Not Found
UseStatusCodePages
通常不會用於生產環境,因為它會傳回對使用者而言不有用的訊息。
注意
狀態字碼頁中介軟體 不會 攔截例外狀況。 若要提供自訂錯誤處理頁面,請使用 例外狀況處理常式頁面。
具格式字串的 UseStatusCodePages
若要自訂回應內容類型和文字,請使用 UseStatusCodePages 的多載,其會採用內容類型和格式字串:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
// using static System.Net.Mime.MediaTypeNames;
app.UseStatusCodePages(Text.Plain, "Status Code Page: {0}");
在上述程式碼中, {0}
是錯誤碼的預留位置。
UseStatusCodePages
使用格式字串通常不會用於生產環境,因為它會傳回對使用者而言不有用的訊息。
具 Lambda 的 UseStatusCodePages
若要指定自訂錯誤處理和回應撰寫程式碼,請使用 UseStatusCodePages 的多載,其會採用 Lambda 運算式:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages(async statusCodeContext =>
{
// using static System.Net.Mime.MediaTypeNames;
statusCodeContext.HttpContext.Response.ContentType = Text.Plain;
await statusCodeContext.HttpContext.Response.WriteAsync(
$"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});
UseStatusCodePages
搭配 Lambda 通常不會用於生產環境,因為它會傳回對使用者而言不有用的訊息。
UseStatusCodePagesWithRedirects
UseStatusCodePagesWithRedirects 擴充方法:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
URL 範本可以包含 {0}
狀態碼的預留位置,如上述程式碼所示。 如果 URL 範本以 ~
(波浪) 開頭,則會 ~
由應用程式的 PathBase
取代。 在應用程式中指定端點時,請為端點建立 MVC 檢視或 Razor 頁面。
此方法通常是在下列應用程式相關情況下使用:
- 應用程式應將用戶端重新導向至不同的端點時 (通常是在由其他應用程式處理錯誤的情況下)。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映重新導向後的端點。
- 應用程式不應該保留並傳回原始狀態碼與初始重新導向回應時。
UseStatusCodePagesWithReExecute
UseStatusCodePagesWithReExecute 擴充方法:
- 可透過使用替代路徑重新執行要求管線來產生回應本文。
- 在重新執行管線之前或之後,不會改變狀態碼。
新的管線執行可能會改變回應的狀態碼,因為新的管線可以完全控制狀態碼。 如果新的管線未改變狀態碼,則會將原始狀態碼傳送至用戶端。
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
如果指定應用程式內的端點,請建立端點的 MVC 檢視或 Razor 頁面。
此方法通常是在下列應用程式相關情況下使用:
- 在不重新導向至其他端點的情況下處理要求。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映原始要求的端點。
- 保留並傳回原始狀態碼與回應時。
URL 範本必須以 /
開頭,而且可能包含狀態碼的預留位置 {0}
。 若要將狀態碼當作查詢字串參數傳遞,請將第二個引數傳遞至 UseStatusCodePagesWithReExecute
。 例如:
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
處理錯誤的端點可以取得產生該錯誤的原始 URL,如下列範例所示:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class StatusCodeModel : PageModel
{
public int OriginalStatusCode { get; set; }
public string? OriginalPathAndQuery { get; set; }
public void OnGet(int statusCode)
{
OriginalStatusCode = statusCode;
var statusCodeReExecuteFeature =
HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature is not null)
{
OriginalPathAndQuery = string.Join(
statusCodeReExecuteFeature.OriginalPathBase,
statusCodeReExecuteFeature.OriginalPath,
statusCodeReExecuteFeature.OriginalQueryString);
}
}
}
由於此中介軟體可以重新執行要求管線:
- 中介軟體必須使用相同的要求來處理重新進入。 這通常表示在呼叫
_next
或快HttpContext
取其處理之後清除其狀態,以避免重做。 處理要求本文時,這表示緩衝處理或快取表單讀取器之類的結果。 - 範圍服務維持不變。
停用狀態碼頁面
若要停用 MVC 控制器或動作方法的狀態碼頁面,請使用 [SkipStatusCodePages] 屬性。
若要停用 Pages 處理常式方法或 MVC 控制器中 Razor 特定要求的狀態字碼頁,請使用 IStatusCodePagesFeature :
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
例外狀況處理程式碼
例外狀況處理頁面中的程式碼也可以擲回例外狀況。 應徹底測試生產錯誤頁面,並小心避免擲回自己的例外狀況。
回應標頭
一旦傳送回應的標頭之後:
- 應用程式就無法變更回應的狀態碼。
- 無法執行任何例外狀況頁面或處理常式。 回應必須完成,否則會中止連線。
伺服器例外狀況處理
除了應用程式中的例外狀況處理邏輯之外, HTTP 伺服器實 作還可以處理一些例外狀況。 如果伺服器在傳送回應標頭之前攔截到例外狀況,則伺服器會傳送 500 - Internal Server Error
沒有回應本文的回應。 如果伺服器在回應標頭傳送之後攔截到例外狀況,伺服器會關閉連線。 應用程式未處理的要求是由伺服器處理。 當伺服器處理要求時,任何發生的例外狀況均由伺服器的例外狀況處理功能來處理。 應用程式的自訂錯誤頁面、例外狀況處理中介軟體或篩選條件並不會影響此行為。
啟動例外狀況處理
只有裝載層可以處理應用程式啟動期間發生的例外狀況。 可以將主機設定為會擷取啟動錯誤和擷取詳細錯誤。
只有在錯誤是於主機位址/連接埠繫結之後發生的情況下,裝載層才能顯示已擷取之啟動錯誤的錯誤頁面。 如果繫結失敗:
- 裝載層會記錄重大例外狀況。
- Dotnet 會處理損毀狀況。
- 當 HTTP 伺服器為 Kestrel 時,不會顯示任何錯誤頁面。
在 IIS (或 Azure App Service) 或 IIS Express 上執行時,如果無法啟動處理序,模組會傳回 502.5 - 處理序失敗。 如需詳細資訊,請參閱針對Azure App 服務 和 IIS 上的 ASP.NET Core進行疑難排解。
資料庫錯誤頁面
資料庫開發人員頁面例外狀況篩選會 AddDatabaseDeveloperPageExceptionFilter 擷取可使用 Entity Framework Core 移轉解析的資料庫相關例外狀況。 發生這些例外狀況時,會產生 HTML 回應,其中包含可能解決問題的動作詳細資料。 此頁面只會在開發環境中啟用。 下列程式碼會新增資料庫開發人員頁面例外狀況篩選器:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
例外狀況篩選條件
在 MVC 應用程式中,您能以全域設定例外狀況篩選條件,或是以每個控制器或每個動作為基礎的方式設定。 在 Razor Pages 應用程式中,可以全域或每一頁面模型設定它們。 這些篩選準則會處理在執行控制器動作或其他篩選期間發生的任何未處理的例外狀況。 如需詳細資訊,請參閱ASP.NET Core 中的篩選。
例外狀況篩選準則對於攔截 MVC 動作內發生的例外狀況很有用,但它們不像內建例外狀況處理中介軟體一樣有彈性。 UseExceptionHandler 建議您使用 UseExceptionHandler
,除非您需要根據選擇的 MVC 動作,以不同的方式執行錯誤處理。
模型狀態錯誤
如需如何處理模型狀態錯誤的相關資訊,請參閱模型繫結和模型驗證。
問題詳細資料
問題詳細資料 不是描述 HTTP API 錯誤的唯一回應格式,不過,通常用來報告 HTTP API 的錯誤。
問題詳細資料服務會實作 IProblemDetailsService 介面,其支援在 ASP.NET Core中建立問題詳細資料。 上的 AddProblemDetails
IServiceCollection 擴充方法會註冊預設 IProblemDetailsService
實作。
在 ASP.NET Core應用程式中,下列中介軟體會在呼叫 時 AddProblemDetails
產生 HTTP 回應的問題詳細資料,但要求 Accept
HTTP 標頭不包含已註冊 IProblemDetailsWriter (預設值所支援的其中一個內容類型:) : application/json
- ExceptionHandlerMiddleware:未定義自訂處理常式時,產生問題詳細資料回應。
- StatusCodePagesMiddleware:預設會產生問題詳細資料回應。
- DeveloperExceptionPageMiddleware:當要求 HTTP 標頭不包含
text/html
時Accept
,在開發中產生問題詳細資料回應。
下列程式碼會將應用程式設定為針對 尚未擁有本文內容的所有 HTTP 用戶端和伺服器錯誤回應產生問題詳細資料回應:
var app = builder.Build();
builder.Services.AddProblemDetails();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
下一節說明如何自訂問題詳細資料回應本文。
自訂問題詳細資料
您可以使用下列任何選項來自訂 自動建立 ProblemDetails
:
- 使用
ProblemDetailsOptions.CustomizeProblemDetails
- 使用自訂
IProblemDetailsWriter
IProblemDetailsService
在中介軟體中呼叫
CustomizeProblemDetails
作業
您可以使用 自訂 CustomizeProblemDetails 產生的問題詳細資料,並將自訂套用至所有自動產生的問題詳細資料。
下列程式碼會使用 ProblemDetailsOptions 來設定 CustomizeProblemDetails :
var app = builder.Build();
builder.Services.AddProblemDetails(options =>
options.CustomizeProblemDetails = ctx =>
ctx.ProblemDetails.Extensions.Add("nodeId", Environment.MachineName));
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
例如, HTTP Status 400 Bad Request
端點結果會產生下列問題詳細資料回應本文:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
自 定義 IProblemDetailsWriter
IProblemDetailsWriter您可以為進階自訂建立實作:
public class SampleProblemDetailsWriter : IProblemDetailsWriter
{
// Indicates that only responses with StatusCode == 400
// are handled by this writer. All others are
// handled by different registered writers if available.
public bool CanWrite(ProblemDetailsContext context)
=> context.HttpContext.Response.StatusCode == 400;
public ValueTask WriteAsync(ProblemDetailsContext context)
{
// Additional customizations.
// Write to the response.
var response = context.HttpContext.Response;
return new ValueTask(response.WriteAsJsonAsync(context.ProblemDetails));
}
}
中介軟體的問題詳細資料
搭配 使用的 ProblemDetailsOptionsCustomizeProblemDetails 替代方法是在中介軟體中設定 ProblemDetails 。 呼叫 即可撰寫 IProblemDetailsService.WriteAsync
問題詳細資料回應:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStatusCodePages();
// Middleware to handle writing problem details to the response.
app.Use(async (context, next) =>
{
await next(context);
var mathErrorFeature = context.Features.Get<MathErrorFeature>();
if (mathErrorFeature is not null)
{
if (context.RequestServices.GetService<IProblemDetailsService>() is
{ } problemDetailsService)
{
(string Detail, string Type) details = mathErrorFeature.MathError switch
{
MathErrorType.DivisionByZeroError => ("Divison by zero is not defined.",
"https://en.wikipedia.org/wiki/Division_by_zero"),
_ => ("Negative or complex numbers are not valid input.",
"https://en.wikipedia.org/wiki/Square_root")
};
await problemDetailsService.WriteAsync(new ProblemDetailsContext
{
HttpContext = context,
ProblemDetails =
{
Title = "Bad Input",
Detail = details.Detail,
Type = details.Type
}
});
}
}
});
// /divide?numerator=2&denominator=4
app.MapGet("/divide", (HttpContext context, double numerator, double denominator) =>
{
if (denominator == 0)
{
var errorType = new MathErrorFeature { MathError =
MathErrorType.DivisionByZeroError };
context.Features.Set(errorType);
return Results.BadRequest();
}
return Results.Ok(numerator / denominator);
});
// /squareroot?radicand=16
app.MapGet("/squareroot", (HttpContext context, double radicand) =>
{
if (radicand < 0)
{
var errorType = new MathErrorFeature { MathError =
MathErrorType.NegativeRadicandError };
context.Features.Set(errorType);
return Results.BadRequest();
}
return Results.Ok(Math.Sqrt(radicand));
});
app.MapControllers();
app.Run();
在上述程式碼中,最小的 API 端點 /divide
,並在 /squareroot
錯誤輸入時傳回預期的自訂問題回應。
API 控制器端點會在錯誤輸入時傳回預設問題回應,而不是自訂問題回應。 系統會傳回預設問題回應,因為 API 控制器已寫入回應資料流程、呼叫之前 IProblemDetailsService.WriteAsync
的錯誤狀態碼問題詳細資料,而且不會再次寫入回應。
下列 ValuesController
會傳 BadRequestResult 回 ,它會寫入回應資料流程,因此會防止傳回自訂問題回應。
[Route("api/[controller]/[action]")]
[ApiController]
public class ValuesController : ControllerBase
{
// /api/values/divide/1/2
[HttpGet("{Numerator}/{Denominator}")]
public IActionResult Divide(double Numerator, double Denominator)
{
if (Denominator == 0)
{
var errorType = new MathErrorFeature
{
MathError = MathErrorType.DivisionByZeroError
};
HttpContext.Features.Set(errorType);
return BadRequest();
}
return Ok(Numerator / Denominator);
}
// /api/values/squareroot/4
[HttpGet("{radicand}")]
public IActionResult Squareroot(double radicand)
{
if (radicand < 0)
{
var errorType = new MathErrorFeature
{
MathError = MathErrorType.NegativeRadicandError
};
HttpContext.Features.Set(errorType);
return BadRequest();
}
return Ok(Math.Sqrt(radicand));
}
}
下列 Values3Controller
會傳 ControllerBase.Problem
回 ,因此會傳回預期的自訂問題結果:
[Route("api/[controller]/[action]")]
[ApiController]
public class Values3Controller : ControllerBase
{
// /api/values3/divide/1/2
[HttpGet("{Numerator}/{Denominator}")]
public IActionResult Divide(double Numerator, double Denominator)
{
if (Denominator == 0)
{
var errorType = new MathErrorFeature
{
MathError = MathErrorType.DivisionByZeroError
};
HttpContext.Features.Set(errorType);
return Problem(
title: "Bad Input",
detail: "Divison by zero is not defined.",
type: "https://en.wikipedia.org/wiki/Division_by_zero",
statusCode: StatusCodes.Status400BadRequest
);
}
return Ok(Numerator / Denominator);
}
// /api/values3/squareroot/4
[HttpGet("{radicand}")]
public IActionResult Squareroot(double radicand)
{
if (radicand < 0)
{
var errorType = new MathErrorFeature
{
MathError = MathErrorType.NegativeRadicandError
};
HttpContext.Features.Set(errorType);
return Problem(
title: "Bad Input",
detail: "Negative or complex numbers are not valid input.",
type: "https://en.wikipedia.org/wiki/Square_root",
statusCode: StatusCodes.Status400BadRequest
);
}
return Ok(Math.Sqrt(radicand));
}
}
產生例外狀況的 ProblemDetails 承載
請考慮下列應用程式:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.MapControllers();
app.Run();
在非開發環境中,當發生例外狀況時,以下是傳回給用戶端的標準 ProblemDetails 回應 :
{
"type":"https://tools.ietf.org/html/rfc7231#section-6.6.1",
"title":"An error occurred while processing your request.",
"status":500,"traceId":"00-b644<snip>-00"
}
對於大部分的應用程式,上述程式碼都是例外狀況所需的所有程式碼。 不過,下一節將示範如何取得更詳細的問題回應。
自訂例外處理常式頁面的替代方法,便是將 Lambda 提供給 UseExceptionHandler。 使用 Lambda 可讓您存取錯誤,並使用 撰寫問題詳細資料回應 IProblemDetailsService.WriteAsync
:
using Microsoft.AspNetCore.Diagnostics;
using static System.Net.Mime.MediaTypeNames;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
context.Response.ContentType = Text.Plain;
var title = "Bad Input";
var detail = "Invalid input";
var type = "https://errors.example.com/badInput";
if (context.RequestServices.GetService<IProblemDetailsService>() is
{ } problemDetailsService)
{
var exceptionHandlerFeature =
context.Features.Get<IExceptionHandlerFeature>();
var exceptionType = exceptionHandlerFeature?.Error;
if (exceptionType != null &&
exceptionType.Message.Contains("infinity"))
{
title = "Arguement exception";
detail = "Invalid input";
type = "https://errors.example.com/arguementException";
}
await problemDetailsService.WriteAsync(new ProblemDetailsContext
{
HttpContext = context,
ProblemDetails =
{
Title = title,
Detail = detail,
Type = type
}
});
}
});
});
}
app.MapControllers();
app.Run();
警告
請勿提供敏感性的錯誤資訊給用戶端。 提供錯誤有安全性風險。
產生問題詳細資料的替代方法是使用協力廠商 NuGet 套件 Hellang.Middleware.ProblemDetails ,可用來將例外狀況和用戶端錯誤對應至問題詳細資料。
其他資源
作者:Tom Dykstra
本文涵蓋處理 ASP.NET Core Web 應用程式中錯誤的常見方法。 請參閱處理 Web API ASP.NET Core Web API 中的錯誤。
開發人員例外頁面
開發人員 例外狀況頁面 會顯示未處理要求例外狀況的詳細資訊。 ASP.NET Core應用程式預設會在兩者都啟用開發人員例外狀況頁面:
- 在 開發環境中執行。
- 使用目前範本建立的應用程式,也就是使用 WebApplication.CreateBuilder。 使用
WebHost.CreateDefaultBuilder
建立的應用程式必須在 中Configure
呼叫app.UseDeveloperExceptionPage
來啟用開發人員例外狀況頁面。
開發人員例外狀況頁面會在中介軟體管線中提早執行,以便攔截在後續中介軟體中擲回的未處理的例外狀況。
應用程式在生產環境中執行時,不應公開顯示詳細的例外狀況資訊。 如需設定環境的詳細資訊,請參閱在 ASP.NET Core中使用多個環境。
開發人員例外狀況頁面可以包含下列有關例外狀況和要求的資訊:
- 堆疊追蹤
- 查詢字串參數,如果有的話
- Cookies,如果有
- 標題
開發人員例外狀況頁面不保證提供任何資訊。 使用 記錄 來取得完整的錯誤資訊。
例外處理常式頁面
若要設定 生產環境的自訂錯誤處理頁面,請呼叫 UseExceptionHandler 。 這個例外狀況處理中介軟體:
- 攔截和記錄未處理的例外狀況。
- 使用指示的路徑,在替代管線中重新執行要求。 如果回應已啟動,就不會重新執行要求。 範本產生的程式碼會使用
/Error
路徑重新執行要求。
警告
如果替代管線擲回本身的例外狀況,例外狀況處理中介軟體會重新擲回原始例外狀況。
在下列範例中, UseExceptionHandler 會在非開發環境中新增例外狀況處理中介軟體:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
RazorPages 應用程式範本會在Pages資料夾中提供 [錯誤] 頁面 (.cshtml
) 和 PageModel 類別 (ErrorModel
) 。 針對 MVC 應用程式,專案範本包含 Error
動作方法和控制器的錯誤 Home 檢視。
例外狀況處理中介軟體會使用 原始 HTTP 方法重新執行要求。 如果錯誤處理常式端點僅限於特定 HTTP 方法集,它只會針對這些 HTTP 方法執行。 例如,使用 屬性的 [HttpGet]
MVC 控制器動作只會針對 GET 要求執行。 為了確保 所有 要求都到達自訂錯誤處理頁面,請勿將它們限制為一組特定的 HTTP 方法。
若要根據原始 HTTP 方法以不同的方式處理例外狀況:
- 針對 Razor Pages,建立多個處理常式方法。 例如,使用
OnGet
來處理 GET 例外狀況,並使用OnPost
來處理 POST 例外狀況。 - 針對 MVC,將 HTTP 動詞屬性套用至多個動作。 例如,使用
[HttpGet]
來處理 GET 例外狀況,並使用[HttpPost]
來處理 POST 例外狀況。
若要允許未經驗證的使用者檢視自訂錯誤處理頁面,請確定它支援匿名存取。
存取例外狀況
使用 IExceptionHandlerPathFeature 來存取錯誤處理常式中的例外狀況和原始要求路徑。 下列範例會使用 IExceptionHandlerPathFeature
來取得擲回之例外狀況的詳細資訊:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string? ExceptionMessage { get; set; }
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
var exceptionHandlerPathFeature =
HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
ExceptionMessage = "The file was not found.";
}
if (exceptionHandlerPathFeature?.Path == "/")
{
ExceptionMessage ??= string.Empty;
ExceptionMessage += " Page: Home.";
}
}
}
警告
請勿提供敏感性的錯誤資訊給用戶端。 提供錯誤有安全性風險。
例外處理常式 Lambda
自訂例外處理常式頁面的替代方法,便是將 Lambda 提供給 UseExceptionHandler。 使用 lambda 可讓您在傳回回應之前存取錯誤。
下列程式碼會使用 Lambda 來處理例外狀況:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler(exceptionHandlerApp =>
{
exceptionHandlerApp.Run(async context =>
{
context.Response.StatusCode = StatusCodes.Status500InternalServerError;
// using static System.Net.Mime.MediaTypeNames;
context.Response.ContentType = Text.Plain;
await context.Response.WriteAsync("An exception was thrown.");
var exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
await context.Response.WriteAsync(" The file was not found.");
}
if (exceptionHandlerPathFeature?.Path == "/")
{
await context.Response.WriteAsync(" Page: Home.");
}
});
});
app.UseHsts();
}
警告
請勿提供敏感性的錯誤資訊給用戶端。 提供錯誤有安全性風險。
UseStatusCodePages
根據預設,ASP.NET Core應用程式不會提供 HTTP 錯誤狀態碼的狀態字碼頁面,例如404 - 找不到。 當應用程式設定沒有本文的 HTTP 400-599 錯誤狀態碼時,它會傳回狀態碼和空的回應本文。 若要啟用常見錯誤狀態碼的預設純文字處理常式,請在 中 Program.cs
呼叫 UseStatusCodePages :
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
在要求處理中介軟體之前呼叫 UseStatusCodePages
。 例如,在靜態檔案中介軟體和端點中介軟體之前呼叫 UseStatusCodePages
。
未使用 時 UseStatusCodePages
,流覽至沒有端點的 URL 會傳回瀏覽器相依的錯誤訊息,指出找不到端點。 呼叫 時 UseStatusCodePages
,瀏覽器會傳回下列回應:
Status Code: 404; Not Found
UseStatusCodePages
通常不會在生產環境中使用,因為它會傳回對使用者沒有説明的訊息。
注意
狀態字碼頁中介軟體 不會 攔截例外狀況。 若要提供自訂錯誤處理頁面,請使用 例外狀況處理常式頁面。
具格式字串的 UseStatusCodePages
若要自訂回應內容類型和文字,請使用 UseStatusCodePages 的多載,其會採用內容類型和格式字串:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
// using static System.Net.Mime.MediaTypeNames;
app.UseStatusCodePages(Text.Plain, "Status Code Page: {0}");
在上述程式碼中, {0}
是錯誤碼的預留位置。
UseStatusCodePages
使用格式字串通常不會用於生產環境,因為它會傳回對使用者而言不正確訊息。
具 Lambda 的 UseStatusCodePages
若要指定自訂錯誤處理和回應撰寫程式碼,請使用 UseStatusCodePages 的多載,其會採用 Lambda 運算式:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages(async statusCodeContext =>
{
// using static System.Net.Mime.MediaTypeNames;
statusCodeContext.HttpContext.Response.ContentType = Text.Plain;
await statusCodeContext.HttpContext.Response.WriteAsync(
$"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});
UseStatusCodePages
搭配 Lambda 通常不會用於生產環境,因為它會傳回對使用者而言不正確訊息。
UseStatusCodePagesWithRedirects
UseStatusCodePagesWithRedirects 擴充方法:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
URL 範本可以包含 {0}
狀態碼的預留位置,如上述程式碼所示。 如果 URL 範本以 ~
(波浪) 開頭,則會 ~
由應用程式的 PathBase
取代。 在應用程式中指定端點時,請建立端點的 MVC 檢視或 Razor 頁面。
此方法通常是在下列應用程式相關情況下使用:
- 應用程式應將用戶端重新導向至不同的端點時 (通常是在由其他應用程式處理錯誤的情況下)。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映重新導向後的端點。
- 應用程式不應該保留並傳回原始狀態碼與初始重新導向回應時。
UseStatusCodePagesWithReExecute
UseStatusCodePagesWithReExecute 擴充方法:
- 傳回原始狀態碼給用戶端。
- 可透過使用替代路徑重新執行要求管線來產生回應本文。
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
如果指定應用程式內的端點,請建立端點的 MVC 檢視或 Razor 頁面。
此方法通常是在下列應用程式相關情況下使用:
- 在不重新導向至其他端點的情況下處理要求。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映原始要求的端點。
- 保留並傳回原始狀態碼與回應時。
URL 範本必須以 開頭 /
,而且可能包含狀態碼的預留位置 {0}
。 若要將狀態碼當作查詢字串參數傳遞,請將第二個引數傳遞至 UseStatusCodePagesWithReExecute
。 例如:
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
處理錯誤的端點可以取得產生該錯誤的原始 URL,如下列範例所示:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class StatusCodeModel : PageModel
{
public int OriginalStatusCode { get; set; }
public string? OriginalPathAndQuery { get; set; }
public void OnGet(int statusCode)
{
OriginalStatusCode = statusCode;
var statusCodeReExecuteFeature =
HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature is not null)
{
OriginalPathAndQuery = string.Join(
statusCodeReExecuteFeature.OriginalPathBase,
statusCodeReExecuteFeature.OriginalPath,
statusCodeReExecuteFeature.OriginalQueryString);
}
}
}
停用狀態碼頁面
若要停用 MVC 控制器或動作方法的狀態碼頁面,請使用 [SkipStatusCodePages] 屬性。
若要停用 Pages 處理常式方法或 MVC 控制器中 Razor 特定要求的狀態字碼頁,請使用 IStatusCodePagesFeature :
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
例外狀況處理程式碼
例外狀況處理頁面中的程式碼也可以擲回例外狀況。 生產錯誤頁面應該徹底測試,並特別小心避免擲回自己的例外狀況。
回應標頭
一旦傳送回應的標頭之後:
- 應用程式就無法變更回應的狀態碼。
- 無法執行任何例外狀況頁面或處理常式。 回應必須完成,否則會中止連線。
伺服器例外狀況處理
除了應用程式中的例外狀況處理邏輯之外, HTTP 伺服器實 作還可以處理某些例外狀況。 如果伺服器在傳送回應標頭之前攔截到例外狀況,伺服器就會傳送 500 - Internal Server Error
沒有回應本文的回應。 如果伺服器在回應標頭傳送之後攔截到例外狀況,伺服器會關閉連線。 應用程式未處理的要求是由伺服器處理。 當伺服器處理要求時,任何發生的例外狀況均由伺服器的例外狀況處理功能來處理。 應用程式的自訂錯誤頁面、例外狀況處理中介軟體或篩選條件並不會影響此行為。
啟動例外狀況處理
只有裝載層可以處理應用程式啟動期間發生的例外狀況。 可以將主機設定為會擷取啟動錯誤和擷取詳細錯誤。
只有在錯誤是於主機位址/連接埠繫結之後發生的情況下,裝載層才能顯示已擷取之啟動錯誤的錯誤頁面。 如果繫結失敗:
- 裝載層會記錄重大例外狀況。
- Dotnet 會處理損毀狀況。
- 當 HTTP 伺服器為 Kestrel 時,不會顯示錯誤頁面。
在 IIS (或 Azure App Service) 或 IIS Express 上執行時,如果無法啟動處理序,模組會傳回 502.5 - 處理序失敗。 如需詳細資訊,請參閱針對Azure App 服務 和 IIS 上的 ASP.NET Core進行疑難排解。
資料庫錯誤頁面
資料庫開發人員頁面例外狀況篩選準則 AddDatabaseDeveloperPageExceptionFilter 會擷取可使用 Entity Framework Core 移轉來解決的資料庫相關例外狀況。 發生這些例外狀況時,會產生 HTML 回應,其中包含可能動作的詳細資料來解決問題。 此頁面只會在開發環境中啟用。 下列程式碼會新增資料庫開發人員頁面例外狀況篩選:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
例外狀況篩選條件
在 MVC 應用程式中,您能以全域設定例外狀況篩選條件,或是以每個控制器或每個動作為基礎的方式設定。 在 Razor Pages 應用程式中,它們可以全域設定或每個頁面模型。 這些篩選準則會處理在控制器動作或其他篩選準則執行期間發生的任何未處理的例外狀況。 如需詳細資訊,請參閱ASP.NET Core中的篩選。
例外狀況篩選準則適用于攔截 MVC 動作內發生的例外狀況,但與內建例外狀況處理中介軟體一樣有彈性。 UseExceptionHandler 除非您需要根據選擇 MVC 動作的不同方式執行錯誤處理,否則建議您使用 UseExceptionHandler
。
模型狀態錯誤
如需如何處理模型狀態錯誤的相關資訊,請參閱模型繫結和模型驗證。
其他資源
作者 :Kirk Larkin、 Tom Dykstra和 Steve Smith
本文涵蓋處理 ASP.NET Core Web 應用程式中錯誤的常見方法。 請參閱處理 Web API ASP.NET Core Web API 中的錯誤。
檢視或下載範例程式碼。 (測試範例應用程式時 ,如何下載.) F12 瀏覽器開發人員工具上的網路索引標籤很有用。
開發人員例外狀況頁面
開發人員 例外狀況頁面 會顯示未處理要求例外狀況的詳細資訊。 ASP.NET Core範本會產生下列程式碼:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
上述醒目提示的程式碼會在開發 環境中執行應用程式時,啟用開發人員例外狀況頁面。
範本會提早放在 UseDeveloperExceptionPage 中介軟體管線中,以便攔截在後續中介軟體中擲回的未處理的例外狀況。
上述程式碼只有在應用程式在開發環境中執行時, 才會 啟用開發人員例外狀況頁面。 應用程式在生產環境中執行時,不應公開顯示詳細的例外狀況資訊。 如需設定環境的詳細資訊,請參閱在 ASP.NET Core中使用多個環境。
開發人員例外狀況頁面可以包含下列有關例外狀況和要求的資訊:
- 堆疊追蹤
- 如果有的話,查詢字串參數
- Cookie如果有任何,則為
- 標題
開發人員例外狀況頁面不保證提供任何資訊。 使用 記錄 來取得完整的錯誤資訊。
例外處理常式頁面
若要設定 生產環境的自訂錯誤處理頁面,請呼叫 UseExceptionHandler 。 這個例外狀況處理中介軟體:
- 攔截和記錄未處理的例外狀況。
- 使用指示的路徑,在替代管線中重新執行要求。 如果回應已啟動,就不會重新執行要求。 範本產生的程式碼會使用
/Error
路徑重新執行要求。
警告
如果替代管線擲回本身的例外狀況,例外狀況處理中介軟體會重新擲回原始例外狀況。
在下列範例中, UseExceptionHandler 會在非開發環境中新增例外狀況處理中介軟體:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
RazorPages 應用程式範本會在Pages資料夾中提供 [錯誤] 頁面 (.cshtml
) 和 PageModel 類別 (ErrorModel
) 。 針對 MVC 應用程式,專案範本包含 Error
動作方法和控制器的錯誤 Home 檢視。
例外狀況處理中介軟體會使用 原始 HTTP 方法重新執行要求。 如果錯誤處理常式端點僅限於特定 HTTP 方法集,它只會針對這些 HTTP 方法執行。 例如,使用 屬性的 [HttpGet]
MVC 控制器動作只會針對 GET 要求執行。 為了確保 所有 要求都到達自訂錯誤處理頁面,請勿將它們限制為一組特定的 HTTP 方法。
若要根據原始 HTTP 方法以不同的方式處理例外狀況:
- 針對 Razor Pages,建立多個處理常式方法。 例如,使用
OnGet
來處理 GET 例外狀況,並使用OnPost
來處理 POST 例外狀況。 - 針對 MVC,將 HTTP 動詞屬性套用至多個動作。 例如,使用
[HttpGet]
來處理 GET 例外狀況,並使用[HttpPost]
來處理 POST 例外狀況。
若要允許未經驗證的使用者檢視自訂錯誤處理頁面,請確定它支援匿名存取。
存取例外狀況
使用 IExceptionHandlerPathFeature 來存取錯誤處理常式中的例外狀況和原始要求路徑。 下列程式碼會新增 ExceptionMessage
至 ASP.NET Core範本所產生的預設值 Pages/Error.cshtml.cs
:
[ResponseCache(Duration=0, Location=ResponseCacheLocation.None, NoStore=true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string ExceptionMessage { get; set; }
private readonly ILogger<ErrorModel> _logger;
public ErrorModel(ILogger<ErrorModel> logger)
{
_logger = logger;
}
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
var exceptionHandlerPathFeature =
HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
ExceptionMessage = "File error thrown";
_logger.LogError(ExceptionMessage);
}
if (exceptionHandlerPathFeature?.Path == "/index")
{
ExceptionMessage += " from home page";
}
}
}
警告
請勿提供敏感性的錯誤資訊給用戶端。 提供錯誤有安全性風險。
若要在 範例應用程式中測試例外狀況:
- 將環境設定為生產環境。
- 從
webBuilder.UseStartup<Startup>();
Program.cs
中移除批註。 - 選取 [觸發首頁上的 例外狀況 ]。
例外處理常式 Lambda
自訂例外處理常式頁面的替代方法,便是將 Lambda 提供給 UseExceptionHandler。 使用 lambda 可讓您在傳回回應之前存取錯誤。
下列程式碼會使用 Lambda 來處理例外狀況:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;;
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
await context.Response.WriteAsync("ERROR!<br><br>\r\n");
var exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
await context.Response.WriteAsync(
"File error thrown!<br><br>\r\n");
}
await context.Response.WriteAsync(
"<a href=\"/\">Home</a><br>\r\n");
await context.Response.WriteAsync("</body></html>\r\n");
await context.Response.WriteAsync(new string(' ', 512));
});
});
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
警告
請勿從 IExceptionHandlerFeature 或 IExceptionHandlerPathFeature 提供錯誤資訊給用戶端。 提供錯誤有安全性風險。
若要在 範例應用程式中測試例外狀況處理 Lambda:
- 將環境設定為生產環境。
- 從
webBuilder.UseStartup<StartupLambda>();
Program.cs
中移除批註。 - 選取 [觸發首頁上的 例外 狀況]。
UseStatusCodePages
根據預設,ASP.NET Core應用程式不會提供 HTTP 錯誤狀態碼的狀態字碼頁面,例如404 - 找不到。 當應用程式設定沒有主體的 HTTP 400-599 錯誤狀態碼時,它會傳回狀態碼和空的回應本文。 若要提供狀態字碼頁,請使用狀態字碼頁中介軟體。 若要針對常見的錯誤狀態碼啟用預設的純文字處理常式,請呼叫 Startup.Configure
方法中的 UseStatusCodePages:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
在要求處理中介軟體之前呼叫 UseStatusCodePages
。 例如,在靜態檔案中介軟體和端點中介軟體之前呼叫 UseStatusCodePages
。
未使用 時 UseStatusCodePages
,流覽至沒有端點的 URL 會傳回瀏覽器相依的錯誤訊息,指出找不到端點。 例如,流覽至 Home/Privacy2
。 呼叫 時 UseStatusCodePages
,瀏覽器會傳回:
Status Code: 404; Not Found
UseStatusCodePages
通常不會用於生產環境,因為它會傳回對使用者而言不有用的訊息。
若要在範例應用程式中進行測試 UseStatusCodePages
:
- 將環境設定為生產環境。
- 從
webBuilder.UseStartup<StartupUseStatusCodePages>();
Program.cs
中移除批註。 - 選取首頁上首頁上的連結。
注意
狀態字碼頁中介軟體 不會 攔截例外狀況。 若要提供自訂錯誤處理頁面,請使用 例外狀況處理常式頁面。
具格式字串的 UseStatusCodePages
若要自訂回應內容類型和文字,請使用 UseStatusCodePages 的多載,其會採用內容類型和格式字串:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages(
"text/plain", "Status code page, status code: {0}");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
在上述程式碼中, {0}
是錯誤碼的預留位置。
UseStatusCodePages
使用格式字串通常不會用於生產環境,因為它會傳回對使用者而言不有用的訊息。
若要在範例應用程式中進行測試 UseStatusCodePages
,請從 webBuilder.UseStartup<StartupFormat>();
Program.cs
中移除批註。
具 Lambda 的 UseStatusCodePages
若要指定自訂錯誤處理和回應撰寫程式碼,請使用 UseStatusCodePages 的多載,其會採用 Lambda 運算式:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages(async context =>
{
context.HttpContext.Response.ContentType = "text/plain";
await context.HttpContext.Response.WriteAsync(
"Status code page, status code: " +
context.HttpContext.Response.StatusCode);
});
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
UseStatusCodePages
搭配 Lambda 通常不會用於生產環境,因為它會傳回對使用者而言不有用的訊息。
若要在範例應用程式中進行測試 UseStatusCodePages
,請從 webBuilder.UseStartup<StartupStatusLambda>();
Program.cs
中移除批註。
UseStatusCodePagesWithRedirects
UseStatusCodePagesWithRedirects 擴充方法:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/MyStatusCode?code={0}");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
URL 範本可以包含 {0}
狀態碼的預留位置,如上述程式碼所示。 如果 URL 範本以 ~
(波浪) 開頭,則會 ~
由應用程式的 PathBase
取代。 在應用程式中指定端點時,請為端點建立 MVC 檢視或 Razor 頁面。 Razor如需 Pages 範例,請參閱範例應用程式中的 Pages/MyStatusCode.cshtml。
此方法通常是在下列應用程式相關情況下使用:
- 應用程式應將用戶端重新導向至不同的端點時 (通常是在由其他應用程式處理錯誤的情況下)。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映重新導向後的端點。
- 應用程式不應該保留並傳回原始狀態碼與初始重新導向回應時。
若要在範例應用程式中進行測試 UseStatusCodePages
,請從 webBuilder.UseStartup<StartupSCredirect>();
Program.cs
中移除批註。
UseStatusCodePagesWithReExecute
UseStatusCodePagesWithReExecute 擴充方法:
- 傳回原始狀態碼給用戶端。
- 可透過使用替代路徑重新執行要求管線來產生回應本文。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/MyStatusCode2", "?code={0}");
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
如果指定應用程式內的端點,請建立端點的 MVC 檢視或 Razor 頁面。 請確定 UseStatusCodePagesWithReExecute
已放置於之前 UseRouting
,以便將要求重新路由傳送至狀態頁面。 Razor如需 Pages 範例,請參閱範例應用程式中的 Pages/MyStatusCode2.cshtml。
此方法通常是在下列應用程式相關情況下使用:
- 在不重新導向至其他端點的情況下處理要求。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映原始要求的端點。
- 保留並傳回原始狀態碼與回應時。
URL 和查詢字串範本可能包含狀態碼的預留位置 {0}
。 URL 範本必須以 /
開頭。
處理錯誤的端點可以取得產生該錯誤的原始 URL,如下列範例所示:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class MyStatusCode2Model : PageModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string ErrorStatusCode { get; set; }
public string OriginalURL { get; set; }
public bool ShowOriginalURL => !string.IsNullOrEmpty(OriginalURL);
public void OnGet(string code)
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
ErrorStatusCode = code;
var statusCodeReExecuteFeature = HttpContext.Features.Get<
IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature != null)
{
OriginalURL =
statusCodeReExecuteFeature.OriginalPathBase
+ statusCodeReExecuteFeature.OriginalPath
+ statusCodeReExecuteFeature.OriginalQueryString;
}
}
}
Razor如需 Pages 範例,請參閱範例應用程式中的 Pages/MyStatusCode2.cshtml。
若要在範例應用程式中進行測試 UseStatusCodePages
,請從 webBuilder.UseStartup<StartupSCreX>();
Program.cs
中移除批註。
停用狀態碼頁面
若要停用 MVC 控制器或動作方法的狀態碼頁面,請使用 [SkipStatusCodePages] 屬性。
若要停用 Pages 處理常式方法或 MVC 控制器中 Razor 特定要求的狀態字碼頁,請使用 IStatusCodePagesFeature :
public void OnGet()
{
// using Microsoft.AspNetCore.Diagnostics;
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
}
例外狀況處理程式碼
例外狀況處理頁面中的程式碼也可以擲回例外狀況。 應徹底測試生產錯誤頁面,並小心避免擲回自己的例外狀況。
回應標頭
一旦傳送回應的標頭之後:
- 應用程式就無法變更回應的狀態碼。
- 無法執行任何例外狀況頁面或處理常式。 回應必須完成,否則會中止連線。
伺服器例外狀況處理
除了應用程式中的例外狀況處理邏輯之外, HTTP 伺服器實 作還可以處理一些例外狀況。 如果伺服器在傳送回應標頭之前攔截到例外狀況,則伺服器會傳送 500 - Internal Server Error
沒有回應本文的回應。 如果伺服器在回應標頭傳送之後攔截到例外狀況,伺服器會關閉連線。 應用程式未處理的要求是由伺服器處理。 當伺服器處理要求時,任何發生的例外狀況均由伺服器的例外狀況處理功能來處理。 應用程式的自訂錯誤頁面、例外狀況處理中介軟體或篩選條件並不會影響此行為。
啟動例外狀況處理
只有裝載層可以處理應用程式啟動期間發生的例外狀況。 可以將主機設定為會擷取啟動錯誤和擷取詳細錯誤。
只有在錯誤是於主機位址/連接埠繫結之後發生的情況下,裝載層才能顯示已擷取之啟動錯誤的錯誤頁面。 如果繫結失敗:
- 裝載層會記錄重大例外狀況。
- Dotnet 會處理損毀狀況。
- 當 HTTP 伺服器為 Kestrel 時,不會顯示任何錯誤頁面。
在 IIS (或 Azure App Service) 或 IIS Express 上執行時,如果無法啟動處理序,模組會傳回 502.5 - 處理序失敗。 如需詳細資訊,請參閱針對Azure App 服務 和 IIS 上的 ASP.NET Core進行疑難排解。
資料庫錯誤頁面
資料庫開發人員頁面例外狀況篩選會 AddDatabaseDeveloperPageExceptionFilter
擷取可使用 Entity Framework Core 移轉解析的資料庫相關例外狀況。 發生這些例外狀況時,會產生 HTML 回應,其中包含可能解決問題的動作詳細資料。 此頁面只會在開發環境中啟用。 指定個別使用者帳戶時,ASP.NET Core Razor Pages 範本會產生下列程式碼:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
}
例外狀況篩選條件
在 MVC 應用程式中,您能以全域設定例外狀況篩選條件,或是以每個控制器或每個動作為基礎的方式設定。 在 Razor Pages 應用程式中,可以全域或每一頁面模型設定它們。 這些篩選準則會處理在執行控制器動作或其他篩選期間發生的任何未處理的例外狀況。 如需詳細資訊,請參閱ASP.NET Core 中的篩選。
例外狀況篩選準則對於攔截 MVC 動作內發生的例外狀況很有用,但它們不像內建例外狀況處理中介軟體一樣有彈性。 UseExceptionHandler
建議您使用 UseExceptionHandler
,除非您需要根據選擇的 MVC 動作,以不同的方式執行錯誤處理。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
模型狀態錯誤
如需如何處理模型狀態錯誤的相關資訊,請參閱模型繫結和模型驗證。
其他資源
本文涵蓋處理 ASP.NET Core Web 應用程式中錯誤的常見方法。 請參閱處理 web API ASP.NET Core Web API 中的錯誤。
檢視或下載範例程式碼。 (如何下載.)
開發人員例外狀況頁面
「開發人員例外狀況頁面」會顯示要求例外狀況的詳細資訊。 ASP.NET Core範本會產生下列程式碼:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
上述程式碼會在開發 環境中執行應用程式時,啟用開發人員例外狀況頁面。
範本會放在 UseDeveloperExceptionPage 任何中介軟體之前,以便在後續的中介軟體中攔截例外狀況。
上述程式碼 只有在應用程式在開發環境中執行時,才會啟用開發人員例外狀況頁面。 當應用程式在生產環境中執行時,不應該公開顯示詳細的例外狀況資訊。 如需設定環境的詳細資訊,請參閱在 ASP.NET Core中使用多個環境。
開發人員例外狀況頁面包含有關例外狀況和要求的下列資訊:
- 堆疊追蹤
- 如果有查詢字串參數
- Cookie如果有任何,則為
- 標題
例外處理常式頁面
若要針對生產環境設定自訂錯誤處理頁面,請使用例外狀況處理中介軟體。 中介軟體:
- 攔截並記錄例外狀況。
- 可在所指示頁面或控制器的替代管線中重新執行要求。 如果回應已啟動,就不會重新執行要求。 範本產生的程式碼會重新執行 對
/Error
的要求。
在下列範例中,UseExceptionHandler 會在非開發環境中加入例外狀況處理中介軟體:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Pages Razor 應用程式範本會在Pages資料夾中提供錯誤頁面 (.cshtml
) 和 PageModel 類別 (ErrorModel
) 。 針對 MVC 應用程式,專案範本會在控制器中包含 Home Error 巨集指令方法和錯誤檢視。
請勿使用 HTTP 方法屬性標記錯誤處理常式動作方法,例如 HttpGet
。 明確的動詞命令可防止某些要求取得方法。 如果未經驗證的使用者應該會看到錯誤檢視,則允許匿名存取方法。
存取例外狀況
使用 IExceptionHandlerPathFeature 來存取例外狀況或和錯誤處理常式控制器或頁面中的原始要求路徑:
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
public string ExceptionMessage { get; set; }
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
var exceptionHandlerPathFeature =
HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
ExceptionMessage = "File error thrown";
}
if (exceptionHandlerPathFeature?.Path == "/index")
{
ExceptionMessage += " from home page";
}
}
}
警告
請勿提供敏感性的錯誤資訊給用戶端。 提供錯誤有安全性風險。
若要觸發上述例外狀況處理頁面,請將環境設定為生產環境,並強制例外狀況。
例外處理常式 Lambda
自訂例外處理常式頁面的替代方法,便是將 Lambda 提供給 UseExceptionHandler。 使用 lambda 可讓您在傳回回應之前存取錯誤。
以下是將 Lambda 用於例外狀況處理的範例:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(errorApp =>
{
errorApp.Run(async context =>
{
context.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
context.Response.ContentType = "text/html";
await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
await context.Response.WriteAsync("ERROR!<br><br>\r\n");
var exceptionHandlerPathFeature =
context.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
{
await context.Response.WriteAsync("File error thrown!<br><br>\r\n");
}
await context.Response.WriteAsync("<a href=\"/\">Home</a><br>\r\n");
await context.Response.WriteAsync("</body></html>\r\n");
await context.Response.WriteAsync(new string(' ', 512)); // IE padding
});
});
app.UseHsts();
}
在上述程式碼中,會新增 , await context.Response.WriteAsync(new string(' ', 512));
因此 Internet Explorer 瀏覽器會顯示錯誤訊息,而不是 IE 錯誤訊息。 如需詳細資訊,請參閱這個 GitHub 問題 \(英文\)。
警告
請勿從 IExceptionHandlerFeature 或 IExceptionHandlerPathFeature 提供錯誤資訊給用戶端。 提供錯誤有安全性風險。
若要在範例應用程式 \(英文\) 中查看例外狀況處理 Lambda 的結果,請使用 ProdEnvironment
和 ErrorHandlerLambda
前置處理器指示詞,並選取首頁上的 [觸發例外狀況]。
UseStatusCodePages
根據預設,ASP.NET Core 應用程式不會提供 HTTP 狀態碼 (例如「404 - 找不到」) 等狀態碼頁面。 應用程式會傳回狀態碼和空白回應主體。 若要提供狀態碼頁面,請使用狀態碼頁面中介軟體。
中介軟體可供 Microsoft.AspNetCore.Diagnostics 套件使用。
若要針對常見的錯誤狀態碼啟用預設的純文字處理常式,請呼叫 Startup.Configure
方法中的 UseStatusCodePages:
app.UseStatusCodePages();
要求處理中介軟體 (例如靜態檔案中介軟體和 MVC 中介軟體) 之前,應該先呼叫 UseStatusCodePages
。
未使用 時 UseStatusCodePages
,流覽至沒有端點的 URL 會傳回瀏覽器相依錯誤訊息,指出找不到端點。 例如,流覽至 Home/Privacy2
。 呼叫 時 UseStatusCodePages
,瀏覽器會傳回:
Status Code: 404; Not Found
具格式字串的 UseStatusCodePages
若要自訂回應內容類型和文字,請使用 UseStatusCodePages 的多載,其會採用內容類型和格式字串:
app.UseStatusCodePages(
"text/plain", "Status code page, status code: {0}");
具 Lambda 的 UseStatusCodePages
若要指定自訂錯誤處理和回應撰寫程式碼,請使用 UseStatusCodePages 的多載,其會採用 Lambda 運算式:
app.UseStatusCodePages(async context =>
{
context.HttpContext.Response.ContentType = "text/plain";
await context.HttpContext.Response.WriteAsync(
"Status code page, status code: " +
context.HttpContext.Response.StatusCode);
});
UseStatusCodePagesWithRedirects
UseStatusCodePagesWithRedirects 擴充方法:
- 傳送「302 - 已找到」狀態碼傳送給用戶端。
- 將用戶端重新導向到 URL 範本中提供的位置。
app.UseStatusCodePagesWithRedirects("/StatusCode?code={0}");
URL 範本可以針對狀態碼包含 {0}
預留位置,如範例所示。 如果 URL 範本以 ~
(波浪) 開頭,則會 ~
由應用程式的 PathBase
取代。 如果您指向應用程式內的端點,請為端點建立 MVC 檢視或 Razor 頁面。 Razor如需 Pages 範例,請參閱 Pages/StatusCode.cshtml
範例應用程式中的 。
此方法通常是在下列應用程式相關情況下使用:
- 應用程式應將用戶端重新導向至不同的端點時 (通常是在由其他應用程式處理錯誤的情況下)。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映重新導向後的端點。
- 應用程式不應該保留並傳回原始狀態碼與初始重新導向回應時。
UseStatusCodePagesWithReExecute
UseStatusCodePagesWithReExecute 擴充方法:
- 傳回原始狀態碼給用戶端。
- 可透過使用替代路徑重新執行要求管線來產生回應本文。
app.UseStatusCodePagesWithReExecute("/StatusCode","?code={0}");
如果您指向應用程式內的端點,請為端點建立 MVC 檢視或 Razor 頁面。 請確定 UseStatusCodePagesWithReExecute
已放置於之前 UseRouting
,以便將要求重新路由傳送至狀態頁面。 Razor如需 Pages 範例,請參閱 Pages/StatusCode.cshtml
範例應用程式中的 。
此方法通常是在下列應用程式相關情況下使用:
- 在不重新導向至其他端點的情況下處理要求。 針對 Web 應用程式,用戶端的瀏覽器網址列會反映原始要求的端點。
- 保留並傳回原始狀態碼與回應時。
URL 和查詢字串範本可能會包含該狀態碼的預留位置 ({0}
)。 URL 範本的開頭必須是斜線 (/
)。 在路徑中使用預留位置時,請確認端點 (頁面或控制器) 可以處理路徑線段。 例如, Razor 錯誤頁面應該接受選擇性路徑區段值與 @page
指示詞:
@page "{code?}"
處理錯誤的端點可以取得產生該錯誤的原始 URL,如下列範例所示:
var statusCodeReExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature != null)
{
OriginalURL =
statusCodeReExecuteFeature.OriginalPathBase
+ statusCodeReExecuteFeature.OriginalPath
+ statusCodeReExecuteFeature.OriginalQueryString;
}
請勿使用 HTTP 方法屬性標記錯誤處理常式動作方法,例如 HttpGet
。 明確的動詞命令可防止某些要求取得方法。 如果未經驗證的使用者應該會看到錯誤檢視,則允許匿名存取方法。
停用狀態碼頁面
若要停用 MVC 控制器或動作方法的狀態字碼頁,請使用 [SkipStatusCodePages]
屬性。
若要停用 Pages 處理常式方法或 MVC 控制器中 Razor 特定要求的狀態字碼頁,請使用 IStatusCodePagesFeature :
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
例外狀況處理程式碼
例外狀況處理頁面中的程式碼,可擲回例外狀況。 一般來說,較好的做法是讓生產環境的錯誤頁面由純靜態內容組成。
回應標頭
一旦傳送回應的標頭之後:
- 應用程式就無法變更回應的狀態碼。
- 無法執行任何例外狀況頁面或處理常式。 回應必須完成,否則會中止連線。
伺服器例外狀況處理
除了應用程式中的例外狀況處理邏輯之外,HTTP 伺服器實作也可以處理一些例外狀況。 如果伺服器在回應標頭傳送之前攔截到例外狀況,伺服器會傳送「500 - 內部伺服器錯誤」回應,且沒有回應本文。 如果伺服器在回應標頭傳送之後攔截到例外狀況,伺服器會關閉連線。 應用程式未處理的要求會由伺服器來處理。 當伺服器處理要求時,任何發生的例外狀況均由伺服器的例外狀況處理功能來處理。 應用程式的自訂錯誤頁面、例外狀況處理中介軟體或篩選條件並不會影響此行為。
啟動例外狀況處理
只有裝載層可以處理應用程式啟動期間發生的例外狀況。 可以將主機設定為會擷取啟動錯誤和擷取詳細錯誤。
只有在錯誤是於主機位址/連接埠繫結之後發生的情況下,裝載層才能顯示已擷取之啟動錯誤的錯誤頁面。 如果繫結失敗:
- 裝載層會記錄重大例外狀況。
- Dotnet 會處理損毀狀況。
- 當 HTTP 伺服器為 Kestrel 時,不會顯示任何錯誤頁面。
在 IIS (或 Azure App Service) 或 IIS Express 上執行時,如果無法啟動處理序,模組會傳回 502.5 - 處理序失敗。 如需詳細資訊,請參閱針對Azure App 服務 和 IIS 上的 ASP.NET Core進行疑難排解。
資料庫錯誤頁面
資料庫錯誤頁面中介軟體會擷取可使用 Entity Framework 移轉解析的資料庫相關例外狀況。 發生這些例外狀況時,系統會產生具解決該問題之可能動作詳細資料的 HTML 回應。 此頁面僅應該於開發環境中啟用。 將程式碼加入 Startup.Configure
來啟用該頁面:
if (env.IsDevelopment())
{
app.UseDatabaseErrorPage();
}
UseDatabaseErrorPage 需要 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet 套件。
例外狀況篩選條件
在 MVC 應用程式中,您能以全域設定例外狀況篩選條件,或是以每個控制器或每個動作為基礎的方式設定。 在 Razor Pages 應用程式中,可以全域或每一頁面模型設定它們。 這些篩選會處理在控制器動作或其他篩選條件執行期間發生但的任何未處理例外狀況。 如需詳細資訊,請參閱ASP.NET Core 中的篩選。
提示
例外狀況篩選條件適合用來截獲 MVC 動作中發生的例外狀況,但是它們並不像例外狀況處理中介軟體那麼有彈性。 我們建議使用中介軟體。 請只在需要根據已選擇的 MVC 動作執行不同的錯誤處理時,才使用篩選條件。
模型狀態錯誤
如需如何處理模型狀態錯誤的相關資訊,請參閱模型繫結和模型驗證。