事件
Power BI DataViz World Championships
2月14日 下午4時 - 3月31日 下午4時
4 次參賽機會,有機會贏得會議套裝行程,現場參與在拉斯維加斯舉行的總決賽
進一步了解備註
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
本文描述如何在控制器型 ASP.NET Core Web API 處理錯誤以及自訂錯誤處理。 如需在基本 API 中錯誤處理的相關資訊,請參閱處理 ASP.NET Core 中的錯誤和在基本 API 中處理錯誤。
「開發人員例外狀況頁面」會顯示未處理要求例外狀況的詳細資訊。 它會使用 DeveloperExceptionPageMiddleware 從 HTTP 管線中擷取同步和非同步例外狀況,並產生錯誤回應。 開發人員例外狀況頁面會在中介軟體管線的早期執行,以便它可以攔截在後續中介軟體中擲回的未處理的例外狀況。
當符合以下兩項條件時,ASP.NET Core 應用程式預設會啟用開發人員例外狀況頁面:
使用舊版範本所建立的應用程式 (也就是使用 WebHost.CreateDefaultBuilder) 可以透過呼叫 app.UseDeveloperExceptionPage
來啟用開發人員例外狀況頁面。
警告
除非應用程式在開發環境中執行,否則請勿啟用 [開發人員例外狀況頁面]。 當應用程式在生產環境中執作時,請不要公開分享詳細的例外狀況資訊。 如需設定環境的詳細資訊,請參閱在 ASP.NET Core 中使用多個環境。
「開發人員例外狀況頁面」可能包含下列有關例外狀況和要求的資訊:
不保證「開發人員例外狀況頁面」提供任何資訊。 請使用記錄來取得完整的錯誤資訊。
下圖顯示了一個範例開發人員例外狀況頁面,並附有動畫來顯示索引標籤和顯示的資訊:
為了回應具有 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。 當要求端點時,此動作會擲回例外狀況。
[HttpGet("Throw")]
public IActionResult Throw() =>
throw new Exception("Sample exception.");
在開發環境中執行此應用程式。
移至控制器動作所定義的端點。
在非開發環境中,使用例外狀況處理中介軟體來產生錯誤承載:
在 Program.cs
中,呼叫 UseExceptionHandler 以新增「例外狀況處理中介軟體」:
var app = builder.Build();
app.UseHttpsRedirection();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/error");
}
app.UseAuthorization();
app.MapControllers();
app.Run();
設定控制器動作,以回應 /error
路由:
[Route("/error")]
public IActionResult HandleError() =>
Problem();
上述 HandleError
動作會將符合 RFC 7807 規範的承載傳送至用戶端。
警告
請不要使用 HTTP 方法屬性 (如 HttpGet
) 來標記錯誤處理常式動作方法。 明確的動詞可防止某些要求到達動作方法。
針對使用 Swagger/OpenAPI 的 Web API,請使用 [ApiExplorerSettings] 屬性來標記錯誤處理常式動作,並將其 IgnoreApi 屬性設定為 true
。 此屬性設定會排除應用程式 OpenAPI 規格的錯誤處理常式動作:
[ApiExplorerSettings(IgnoreApi = true)]
如果未經驗證的使用者應該看到錯誤,則允許匿名存取方法。
「例外狀況處理中介軟體」也可以用於開發環境,以產生跨所有環境的一致承載格式:
在 Program.cs
中,註冊環境特定的「例外狀況處理中介軟體」執行個體:
if (app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/error-development");
}
else
{
app.UseExceptionHandler("/error");
}
在上述程式碼中,會向下列項目註冊中介軟體:
/error-development
的路由。/error
的路由。新增開發和非開發路由的控制器動作:
[Route("/error-development")]
public IActionResult HandleErrorDevelopment(
[FromServices] IHostEnvironment hostEnvironment)
{
if (!hostEnvironment.IsDevelopment())
{
return NotFound();
}
var exceptionHandlerFeature =
HttpContext.Features.Get<IExceptionHandlerFeature>()!;
return Problem(
detail: exceptionHandlerFeature.Error.StackTrace,
title: exceptionHandlerFeature.Error.Message);
}
[Route("/error")]
public IActionResult HandleError() =>
Problem();
使用自訂例外狀況和動作篩選,可以從控制器外部修改回應的內容:
建立名為 HttpResponseException
的已知例外狀況類型:
public class HttpResponseException : Exception
{
public HttpResponseException(int statusCode, object? value = null) =>
(StatusCode, Value) = (statusCode, value);
public int StatusCode { get; }
public object? Value { get; }
}
建立名為 HttpResponseExceptionFilter
的動作篩選:
public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order => int.MaxValue - 10;
public void OnActionExecuting(ActionExecutingContext context) { }
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is HttpResponseException httpResponseException)
{
context.Result = new ObjectResult(httpResponseException.Value)
{
StatusCode = httpResponseException.StatusCode
};
context.ExceptionHandled = true;
}
}
}
上述篩選指定最大整數值減 10 的 Order
。 此 Order
允許在管線結尾執行其他篩選。
在 Program.cs
中,將動作篩選新增至 filters 集合:
builder.Services.AddControllers(options =>
{
options.Filters.Add<HttpResponseExceptionFilter>();
});
針對 Web API 控制器,MVC 會在模型驗證失敗時回應 ValidationProblemDetails 回應類型。 MVC 會使用 InvalidModelStateResponseFactory 的結果來建構驗證失敗的錯誤回應。 下列範例會在 Program.cs
中將預設處理站取代為也支援將回應格式化為 XML 的實作:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
new BadRequestObjectResult(context.ModelState)
{
ContentTypes =
{
// using static System.Net.Mime.MediaTypeNames;
Application.Json,
Application.Xml
}
};
})
.AddXmlSerializerFormatters();
「錯誤結果」定義為 HTTP 狀態碼為 400 或更高值的結果。 針對 Web API 控制器,MVC 會轉換錯誤結果,以產生 ProblemDetails。
預設會啟用自動建立 ProblemDetails
錯誤狀態碼,但可以使用下列其中一種方式來設定錯誤回應:
下列 Program.cs
檔案是由 API 控制器的 Web 應用程式範本所產生:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
請考慮下列控制器,其會在輸入無效時傳回 BadRequest:
[Route("api/[controller]/[action]")]
[ApiController]
public class Values2Controller : ControllerBase
{
// /api/values2/divide/1/2
[HttpGet("{Numerator}/{Denominator}")]
public IActionResult Divide(double Numerator, double Denominator)
{
if (Denominator == 0)
{
return BadRequest();
}
return Ok(Numerator / Denominator);
}
// /api/values2 /squareroot/4
[HttpGet("{radicand}")]
public IActionResult Squareroot(double radicand)
{
if (radicand < 0)
{
return BadRequest();
}
return Ok(Math.Sqrt(radicand));
}
}
下列任一條件適用時,會使用上述程式碼產生問題詳細資料回應:
/api/values2/divide
端點。/api/values2/squareroot
端點。預設問題詳細資料回應本文具有下列 type
、title
和 status
值:
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "Bad Request",
"status": 400,
"traceId": "00-84c1fd4063c38d9f3900d06e56542d48-85d1d4-00"
}
ASP.NET Core 支援使用 IProblemDetailsService 來建立 HTTP API 的問題詳細資料。 如需詳細資訊,請參閱問題詳細資料服務。
下列程式碼會將應用程式設定為產生所有 HTTP 用戶端和伺服器錯誤回應的問題詳細資料回應,而這些錯誤回應「還沒有本文內容」:
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();
請考慮上節中的 API 控制器,其會在輸入無效時傳回 BadRequest:
[Route("api/[controller]/[action]")]
[ApiController]
public class Values2Controller : ControllerBase
{
// /api/values2/divide/1/2
[HttpGet("{Numerator}/{Denominator}")]
public IActionResult Divide(double Numerator, double Denominator)
{
if (Denominator == 0)
{
return BadRequest();
}
return Ok(Numerator / Denominator);
}
// /api/values2 /squareroot/4
[HttpGet("{radicand}")]
public IActionResult Squareroot(double radicand)
{
if (radicand < 0)
{
return BadRequest();
}
return Ok(Math.Sqrt(radicand));
}
}
下列任一條件適用時,會使用上述程式碼產生問題詳細資料回應:
當 SuppressMapClientErrors 屬性設定為 true
時,系統會停用自動為錯誤狀態碼建立 ProblemDetails
的動作:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressMapClientErrors = true;
});
var app = builder.Build();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
如果使用上述程式碼,則在 API 控制器傳回 BadRequest
時,不會傳回 HTTP 400 回應狀態,而且沒有回應本文。 SuppressMapClientErrors
可防止建立 ProblemDetails
回應,即使針對 API 控制器端點呼叫 WriteAsync
時也是一樣。 本文稍後將說明 WriteAsync
。
下節顯示如何使用 CustomizeProblemDetails 來自訂問題詳細資料回應本文,以傳回更實用的回應。 如需更多自訂選項,請參閱自訂問題詳細資料。
下列程式碼會使用 ProblemDetailsOptions 來設定 CustomizeProblemDetails:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddProblemDetails(options =>
options.CustomizeProblemDetails = (context) =>
{
var mathErrorFeature = context.HttpContext.Features
.Get<MathErrorFeature>();
if (mathErrorFeature is not null)
{
(string Detail, string Type) details = mathErrorFeature.MathError switch
{
MathErrorType.DivisionByZeroError =>
("Divison by zero is not defined.",
"https://wikipedia.org/wiki/Division_by_zero"),
_ => ("Negative or complex numbers are not valid input.",
"https://wikipedia.org/wiki/Square_root")
};
context.ProblemDetails.Type = details.Type;
context.ProblemDetails.Title = "Bad Input";
context.ProblemDetails.Detail = details.Detail;
}
}
);
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStatusCodePages();
app.UseAuthorization();
app.MapControllers();
app.Run();
已更新的 API 控制器:
[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));
}
}
下列程式碼包含 MathErrorFeature
和 MathErrorType
,其與上述範例搭配使用:
// Custom Http Request Feature
class MathErrorFeature
{
public MathErrorType MathError { get; set; }
}
// Custom math errors
enum MathErrorType
{
DivisionByZeroError,
NegativeRadicandError
}
下列任一條件適用時,會使用上述程式碼產生問題詳細資料回應:
/divide
端點。/squareroot
端點。使用小於零的弧度來呼叫其中一個 squareroot
端點時,問題詳細資料回應本文會包含下列項目:
{
"type": "https://en.wikipedia.org/wiki/Square_root",
"title": "Bad Input",
"status": 400,
"detail": "Negative or complex numbers are not allowed."
}
MVC 會使用 Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory 來產生所有 ProblemDetails 和 ValidationProblemDetails 執行個體。 此處理站用於:
若要自訂問題詳細資料回應,請在 Program.cs
中註冊 ProblemDetailsFactory 的自訂實作:
builder.Services.AddControllers();
builder.Services.AddTransient<ProblemDetailsFactory, SampleProblemDetailsFactory>();
使用 ClientErrorMapping 屬性可設定 ProblemDetails
回應的內容。 例如,Program.cs
中的下列程式碼會更新 404 回應的 Link 屬性:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
本文描述如何使用 ASP.NET Core Web API 來處理錯誤以及自訂錯誤處理。
開發人員例外狀況頁面會顯示詳細的伺服器錯誤堆疊追蹤。 它會使用 DeveloperExceptionPageMiddleware 從 HTTP 管線中擷取同步和非同步例外狀況,並產生錯誤回應。 例如,請考慮下列控制器動作,而此動作會擲回例外狀況:
[HttpGet("Throw")]
public IActionResult Throw() =>
throw new Exception("Sample exception.");
「開發人員例外狀況頁面」偵測到未處理的例外狀況時,會產生與下列範例類似的預設純文字回應:
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked
System.Exception: Sample exception.
at HandleErrorsSample.Controllers.ErrorsController.Get() in ...
at lambda_method1(Closure , Object , Object[] )
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
...
如果用戶端要求 HTML 格式化回應,則「開發人員例外狀況頁面」會產生與下列範例類似的回應:
HTTP/1.1 500 Internal Server Error
Content-Type: text/html; charset=utf-8
Server: Kestrel
Transfer-Encoding: chunked
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Internal Server Error</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
color: #222;
background-color: #fff;
}
h1 {
color: #44525e;
margin: 15px 0 15px 0;
}
...
若要要求 HTML 格式化回應,請將 Accept
HTTP 要求標頭設定為 text/html
。
警告
除非應用程式在開發環境中執行,否則請勿啟用 [開發人員例外狀況頁面]。 當應用程式在生產環境中執作時,請不要公開分享詳細的例外狀況資訊。 如需設定環境的詳細資訊,請參閱在 ASP.NET Core 中使用多個環境。
在非開發環境中,使用例外狀況處理中介軟體來產生錯誤承載:
在 Program.cs
中,呼叫 UseExceptionHandler 以新增「例外狀況處理中介軟體」:
var app = builder.Build();
app.UseHttpsRedirection();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/error");
}
app.UseAuthorization();
app.MapControllers();
app.Run();
設定控制器動作,以回應 /error
路由:
[Route("/error")]
public IActionResult HandleError() =>
Problem();
上述 HandleError
動作會將符合 RFC 7807 規範的承載傳送至用戶端。
警告
請不要使用 HTTP 方法屬性 (如 HttpGet
) 來標記錯誤處理常式動作方法。 明確的動詞可防止某些要求到達動作方法。
針對使用 Swagger/OpenAPI 的 Web API,請使用 [ApiExplorerSettings] 屬性來標記錯誤處理常式動作,並將其 IgnoreApi 屬性設定為 true
。 此屬性設定會排除應用程式 OpenAPI 規格的錯誤處理常式動作:
[ApiExplorerSettings(IgnoreApi = true)]
如果未經驗證的使用者應該看到錯誤,則允許匿名存取方法。
「例外狀況處理中介軟體」也可以用於開發環境,以產生跨所有環境的一致承載格式:
在 Program.cs
中,註冊環境特定的「例外狀況處理中介軟體」執行個體:
if (app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/error-development");
}
else
{
app.UseExceptionHandler("/error");
}
在上述程式碼中,會向下列項目註冊中介軟體:
/error-development
的路由。/error
的路由。新增開發和非開發路由的控制器動作:
[Route("/error-development")]
public IActionResult HandleErrorDevelopment(
[FromServices] IHostEnvironment hostEnvironment)
{
if (!hostEnvironment.IsDevelopment())
{
return NotFound();
}
var exceptionHandlerFeature =
HttpContext.Features.Get<IExceptionHandlerFeature>()!;
return Problem(
detail: exceptionHandlerFeature.Error.StackTrace,
title: exceptionHandlerFeature.Error.Message);
}
[Route("/error")]
public IActionResult HandleError() =>
Problem();
使用自訂例外狀況和動作篩選,可以從控制器外部修改回應的內容:
建立名為 HttpResponseException
的已知例外狀況類型:
public class HttpResponseException : Exception
{
public HttpResponseException(int statusCode, object? value = null) =>
(StatusCode, Value) = (statusCode, value);
public int StatusCode { get; }
public object? Value { get; }
}
建立名為 HttpResponseExceptionFilter
的動作篩選:
public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order => int.MaxValue - 10;
public void OnActionExecuting(ActionExecutingContext context) { }
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is HttpResponseException httpResponseException)
{
context.Result = new ObjectResult(httpResponseException.Value)
{
StatusCode = httpResponseException.StatusCode
};
context.ExceptionHandled = true;
}
}
}
上述篩選指定最大整數值減 10 的 Order
。 此 Order
允許在管線結尾執行其他篩選。
在 Program.cs
中,將動作篩選新增至 filters 集合:
builder.Services.AddControllers(options =>
{
options.Filters.Add<HttpResponseExceptionFilter>();
});
針對 Web API 控制器,MVC 會在模型驗證失敗時回應 ValidationProblemDetails 回應類型。 MVC 會使用 InvalidModelStateResponseFactory 的結果來建構驗證失敗的錯誤回應。 下列範例會在 Program.cs
中將預設處理站取代為也支援將回應格式化為 XML 的實作:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
new BadRequestObjectResult(context.ModelState)
{
ContentTypes =
{
// using static System.Net.Mime.MediaTypeNames;
Application.Json,
Application.Xml
}
};
})
.AddXmlSerializerFormatters();
「錯誤結果」定義為 HTTP 狀態碼為 400 或更高值的結果。 針對 Web API 控制器,MVC 會轉換錯誤結果,以產生 ProblemDetails。
錯誤回應可以透過下列其中一種方式進行設定:
MVC 會使用 Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory 來產生所有 ProblemDetails 和 ValidationProblemDetails 執行個體。 此處理站用於:
若要自訂問題詳細資料回應,請在 Program.cs
中註冊 ProblemDetailsFactory 的自訂實作:
builder.Services.AddControllers();
builder.Services.AddTransient<ProblemDetailsFactory, SampleProblemDetailsFactory>();
使用 ClientErrorMapping 屬性可設定 ProblemDetails
回應的內容。 例如,Program.cs
中的下列程式碼會更新 404 回應的 Link 屬性:
builder.Services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
});
例外狀況處理中介軟體中的預設值適用於大部分的應用程式。 針對需要特殊化例外狀況處理的應用程式,請考慮自訂例外狀況處理中介軟體。
發生未處理的例外狀況時,ASP.NET Core 不會產生標準化錯誤承載。 針對想要將標準化 ProblemDetails 回應傳回給用戶端的案例,可以使用 ProblemDetails 中介軟體以將例外狀況和 404 回應對應至 ProblemDetails 承載。 例外狀況處理中介軟體也可以用來傳回未處理例外狀況的 ProblemDetails 承載。
本文描述如何使用 ASP.NET Core Web API 來處理和自訂錯誤處理。
開發人員例外狀況頁面是一個有用的工具,可取得詳細的伺服器錯誤堆疊追蹤。 它會使用 DeveloperExceptionPageMiddleware 從 HTTP 管線中擷取同步和非同步例外狀況,並產生錯誤回應。 若要說明,請考慮下列控制器動作:
[HttpGet("{city}")]
public WeatherForecast Get(string city)
{
if (!string.Equals(city?.TrimEnd(), "Redmond", StringComparison.OrdinalIgnoreCase))
{
throw new ArgumentException(
$"We don't offer a weather forecast for {city}.", nameof(city));
}
return GetWeather().First();
}
執行下列 curl
命令來測試上述動作:
curl -i https://localhost:5001/weatherforecast/chicago
如果用戶端未要求 HTML 格式化輸出,則「開發人員例外狀況頁面」會顯示純文字回應。 會出現下列輸出:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/plain
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Fri, 27 Sep 2019 16:13:16 GMT
System.ArgumentException: We don't offer a weather forecast for chicago. (Parameter 'city')
at WebApiSample.Controllers.WeatherForecastController.Get(String city) in C:\working_folder\aspnet\AspNetCore.Docs\aspnetcore\web-api\handle-errors\samples\3.x\Controllers\WeatherForecastController.cs:line 34
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Host: localhost:44312
User-Agent: curl/7.55.1
若要改為顯示 HTML 格式化回應,請將 Accept
HTTP 要求標頭設定為 text/html
媒體類型。 例如:
curl -i -H "Accept: text/html" https://localhost:5001/weatherforecast/chicago
請考慮 HTTP 回應中的下列摘錄:
HTTP/1.1 500 Internal Server Error
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Fri, 27 Sep 2019 16:55:37 GMT
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Internal Server Error</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Arial, Helvetica, sans-serif;
font-size: .813em;
color: #222;
background-color: #fff;
}
透過 curl 這類工具進行測試時,HTML 格式化回應會變得十分有用。
警告
僅有當應用程式是在開發環境中執行時,才啟用開發人員例外狀況頁面。 當應用程式在生產環境中執作時,請不要公開分享詳細的例外狀況資訊。 如需設定環境的詳細資訊,請參閱在 ASP.NET Core 中使用多個環境。
請不要使用 HTTP 方法屬性 (如 HttpGet
) 來標記錯誤處理常式動作方法。 明確的動詞可防止某些要求到達動作方法。 如果未經驗證的使用者應該看到錯誤,則允許匿名存取方法。
在非開發環境中,可以使用例外狀況處理中介軟體來產生錯誤承載:
在 Startup.Configure
中,叫用 UseExceptionHandler 以使用中介軟體:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
設定控制器動作,以回應 /error
路由:
[ApiController]
public class ErrorController : ControllerBase
{
[Route("/error")]
public IActionResult Error() => Problem();
}
上述 Error
動作會將符合 RFC 7807 規範的承載傳送至用戶端。
「例外狀況處理中介軟體」也可以在本機開發環境中提供更詳細的內容交涉輸出。 使用下列步驟,以產生跨開發和生產環境的一致承載格式:
在 Startup.Configure
中,註冊環境特定的「例外狀況處理中介軟體」執行個體:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseExceptionHandler("/error-local-development");
}
else
{
app.UseExceptionHandler("/error");
}
}
在上述程式碼中,會向下列項目註冊中介軟體:
/error-local-development
的路由。/error
的路由。將屬性路由套用至控制器動作:
[ApiController]
public class ErrorController : ControllerBase
{
[Route("/error-local-development")]
public IActionResult ErrorLocalDevelopment(
[FromServices] IWebHostEnvironment webHostEnvironment)
{
if (webHostEnvironment.EnvironmentName != "Development")
{
throw new InvalidOperationException(
"This shouldn't be invoked in non-development environments.");
}
var context = HttpContext.Features.Get<IExceptionHandlerFeature>();
return Problem(
detail: context.Error.StackTrace,
title: context.Error.Message);
}
[Route("/error")]
public IActionResult Error() => Problem();
}
上述程式碼會呼叫 ControllerBase.Problem 來建立 ProblemDetails 回應。
可以從控制器外部修改回應的內容。 在 ASP.NET 4.x Web API 中,執行此作業的其中一種方式是使用 HttpResponseException 類型。 ASP.NET Core 未包括對等的類型。 您可以使用下列步驟來新增 HttpResponseException
的支援:
建立名為 HttpResponseException
的已知例外狀況類型:
public class HttpResponseException : Exception
{
public int Status { get; set; } = 500;
public object Value { get; set; }
}
建立名為 HttpResponseExceptionFilter
的動作篩選:
public class HttpResponseExceptionFilter : IActionFilter, IOrderedFilter
{
public int Order { get; } = int.MaxValue - 10;
public void OnActionExecuting(ActionExecutingContext context) { }
public void OnActionExecuted(ActionExecutedContext context)
{
if (context.Exception is HttpResponseException exception)
{
context.Result = new ObjectResult(exception.Value)
{
StatusCode = exception.Status,
};
context.ExceptionHandled = true;
}
}
}
上述篩選指定最大整數值減 10 的 Order
。 此 Order
允許在管線結尾執行其他篩選。
在 Startup.ConfigureServices
中,將動作篩選新增至 filters 集合:
services.AddControllers(options =>
options.Filters.Add(new HttpResponseExceptionFilter()));
針對 Web API 控制器,MVC 會在模型驗證失敗時回應 ValidationProblemDetails 回應類型。 MVC 會使用 InvalidModelStateResponseFactory 的結果來建構驗證失敗的錯誤回應。 下列範例會使用處理站以將預設回應類型變更為 Startup.ConfigureServices
中的 SerializableError:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var result = new BadRequestObjectResult(context.ModelState);
// TODO: add `using System.Net.Mime;` to resolve MediaTypeNames
result.ContentTypes.Add(MediaTypeNames.Application.Json);
result.ContentTypes.Add(MediaTypeNames.Application.Xml);
return result;
};
});
「錯誤結果」定義為 HTTP 狀態碼為 400 或更高值的結果。 針對 Web API 控制器,MVC 會將錯誤結果轉換為具有 ProblemDetails 的結果。
錯誤回應可以透過下列其中一種方式進行設定:
MVC 會使用 Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory 來產生所有 ProblemDetails 和 ValidationProblemDetails 執行個體。 此處理站用於:
若要自訂問題詳細資料回應,請在 Startup.ConfigureServices
中註冊 ProblemDetailsFactory 的自訂實作:
public void ConfigureServices(IServiceCollection serviceCollection)
{
services.AddControllers();
services.AddTransient<ProblemDetailsFactory, CustomProblemDetailsFactory>();
}
使用 ClientErrorMapping 屬性可設定 ProblemDetails
回應的內容。 例如,Startup.ConfigureServices
中的下列程式碼會更新 404 回應的 type
屬性:
services.AddControllers()
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[StatusCodes.Status404NotFound].Link =
"https://httpstatuses.com/404";
options.DisableImplicitFromServicesParameters = true;
});
例外狀況處理中介軟體中的預設值適用於大部分的應用程式。 針對需要特殊化例外狀況處理的應用程式,請考慮自訂例外狀況處理中介軟體。
發生未處理的例外狀況時,ASP.NET Core 不會產生標準化錯誤承載。 針對想要將標準化 ProblemDetails 回應傳回給用戶端的案例,可以使用 ProblemDetails 中介軟體以將例外狀況和 404 回應對應至 ProblemDetails 承載。 例外狀況處理中介軟體也可以用來傳回未處理例外狀況的 ProblemDetails 承載。
事件
Power BI DataViz World Championships
2月14日 下午4時 - 3月31日 下午4時
4 次參賽機會,有機會贏得會議套裝行程,現場參與在拉斯維加斯舉行的總決賽
進一步了解