Web API'ASP.NET Core hataları işleme
Bu makalede web API'leriyle hata işlemeyi nasıl ASP.NET Core ve özelleştirebileceğiniz açıklanmıştır.
Örnek kodu görüntüleme veya indirme (İndirme)
Geliştirici Özel Durum Sayfası
Geliştirici Özel Durum Sayfası, sunucu hatalarına ilişkin ayrıntılı yığın izlemeleri almak için kullanışlı bir araçtır. HTTP işlem hattından zaman uyumlu ve zaman uyumsuz özel durumları yakalamak ve hata DeveloperExceptionPageMiddleware yanıtları oluşturmak için kullanır. Göstermek için aşağıdaki denetleyici eylemlerini göz önünde kullanın:
[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();
}
Önceki eylemi curl test etmek için aşağıdaki komutu çalıştırın:
curl -i https://localhost:5001/weatherforecast/chicago
Bu ASP.NET Core 3.0 ve sonraki bir sürümünün ardından, istemci HTML biçimli çıkış isteğinde bulunsa bile Geliştirici Özel Durum Sayfası düz metin yanıtı görüntüler. Aşağıdaki çıkış görüntülenir:
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
Bunun yerine HTML biçimli bir yanıt görüntülemek için, HTTP isteği Accept üst bilgisini medya text/html türüne ayarlayın. Örnek:
curl -i -H "Accept: text/html" https://localhost:5001/weatherforecast/chicago
HTTP yanıttan aşağıdaki alıntıyı düşünün:
2 ASP.NET Core 2.2 ve önceki sürümlerde, Geliştirici Özel Durum Sayfası HTML biçimli bir yanıt görüntüler. Örneğin, HTTP yanıttan aşağıdaki alıntıyı düşünün:
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;
}
HTML biçimli yanıt, Postman gibi araçlar aracılığıyla test etme sırasında yararlı olur. Aşağıdaki ekran yakalama, Postman'de hem düz metin hem de HTML biçimli yanıtları gösterir:

Uyarı
Geliştirici Özel Durum Sayfası'nın yalnızca uygulama Geliştirme ortamında çalışıyor olduğunda etkinleştirin. Uygulama üretimde çalıştırıldıklarında ayrıntılı özel durum bilgilerini herkese açık şekilde paylaşmayın. Ortamları yapılandırma hakkında daha fazla bilgi için bkz. ASP.NET Core'da birden çok ortam kullanma .
Hata işleyici eylem yöntemini gibi HTTP yöntemi öznitelikleriyle HttpGet işaretlemeyin. Açık fiiller bazı isteklerin eylem yöntemine ulaşmasını önler. Kimliği doğrulanmamış kullanıcıların hatayı görmeleri gerekirse yöntemine anonim erişime izin ver.
Özel durum işleyicisi
Geliştirme dışı ortamlarda, hata yükü üretmek için Özel Durum İşleme Ara Yazılımı kullanılabilir:
içinde
Startup.Configureara yazılımı kullanmak için UseExceptionHandler çağır: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(); }); }public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); }Rotaya yanıt vermek için bir denetleyici eylemi
/erroryapılandırma:[ApiController] public class ErrorController : ControllerBase { [Route("/error")] public IActionResult Error() => Problem(); }[ApiController] public class ErrorController : ControllerBase { [Route("/error")] public ActionResult Error([FromServices] IHostingEnvironment webHostEnvironment) { var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>(); var ex = feature?.Error; var isDev = webHostEnvironment.IsDevelopment(); var problemDetails = new ProblemDetails { Status = (int)HttpStatusCode.InternalServerError, Instance = feature?.Path, Title = isDev ? $"{ex.GetType().Name}: {ex.Message}" : "An error occurred.", Detail = isDev ? ex.StackTrace : null, }; return StatusCode(problemDetails.Status.Value, problemDetails); } }
Yukarıdaki Error eylem, istemciye RFC 7807uyumlu bir yük gönderir.
Özel Durum İşleme Ara Yazılımı, yerel geliştirme ortamında daha ayrıntılı içerik anlaşması yapılan çıkış da sağlar. Geliştirme ve üretim ortamlarında tutarlı bir yük biçimi üretmek için aşağıdaki adımları kullanın:
içinde,
Startup.Configureortama özgü Özel Durum İşleme Ara Yazılım örneklerini kaydetme:public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseExceptionHandler("/error-local-development"); } else { app.UseExceptionHandler("/error"); } }public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseExceptionHandler("/error-local-development"); } else { app.UseExceptionHandler("/error"); } }Yukarıdaki kodda ara yazılım şu şekilde kaydedilir:
- Geliştirme
/error-local-developmentortamındaki bir yolu. - Geliştirme olmayan
/errorortamlardaki bir yolu.
- Geliştirme
Denetleyici eylemlerine öznitelik yönlendirmesi uygulama:
[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(); }[ApiController] public class ErrorController : ControllerBase { [Route("/error-local-development")] public IActionResult ErrorLocalDevelopment( [FromServices] IHostingEnvironment webHostEnvironment) { if (!webHostEnvironment.IsDevelopment()) { throw new InvalidOperationException( "This shouldn't be invoked in non-development environments."); } var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>(); var ex = feature?.Error; var problemDetails = new ProblemDetails { Status = (int)HttpStatusCode.InternalServerError, Instance = feature?.Path, Title = ex.GetType().Name, Detail = ex.StackTrace, }; return StatusCode(problemDetails.Status.Value, problemDetails); } [Route("/error")] public ActionResult Error( [FromServices] IHostingEnvironment webHostEnvironment) { var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>(); var ex = feature?.Error; var isDev = webHostEnvironment.IsDevelopment(); var problemDetails = new ProblemDetails { Status = (int)HttpStatusCode.InternalServerError, Instance = feature?.Path, Title = isDev ? $"{ex.GetType().Name}: {ex.Message}" : "An error occurred.", Detail = isDev ? ex.StackTrace : null, }; return StatusCode(problemDetails.Status.Value, problemDetails); } }Yukarıdaki kod, bir yanıt oluşturmak için ControllerBase.Problem'i ProblemDetails çağırıyor.
Yanıtı değiştirmek için özel durumları kullanma
Yanıtın içeriği denetleyicinin dışından değiştirilebilir. Bu ASP.NET 4.x Web API'sinde bunu yapma yollarından biri türünü HttpResponseException kullanmaktır. ASP.NET Core eşdeğer bir tür içermez. desteği HttpResponseException aşağıdaki adımlarla eklenebilir:
adlı iyi bilinen bir özel durum türü
HttpResponseExceptionoluşturun:public class HttpResponseException : Exception { public int Status { get; set; } = 500; public object Value { get; set; } }adlı bir eylem filtresi
HttpResponseExceptionFilteroluşturun: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; } } }Yukarıdaki filtre, maksimum tamsayı
Orderdeğerinin eksi 10 değerini belirtir. Bu işlem hattının sonunda diğer filtrelerin çalışmasına olanak sağlar.içinde,
Startup.ConfigureServiceseylem filtresini filtreler koleksiyonuna ekleyin:services.AddControllers(options => options.Filters.Add(new HttpResponseExceptionFilter()));services.AddMvc(options => options.Filters.Add(new HttpResponseExceptionFilter())) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);services.AddMvc(options => options.Filters.Add(new HttpResponseExceptionFilter())) .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
Doğrulama hatası hata yanıtı
Web API'si denetleyicileri için MVC, model doğrulama ValidationProblemDetails başarısız olduğunda yanıt türüyle yanıt verir. MVC, doğrulama hatası InvalidModelStateResponseFactory için hata yanıtını oluşturmak için sonuçlarını kullanır. Aşağıdaki örnek, içinde varsayılan yanıt türünü olarak değiştirmek için fabrikayı SerializableError Startup.ConfigureServices kullanır:
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;
};
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.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;
};
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.Configure<ApiBehaviorOptions>(options =>
{
options.InvalidModelStateResponseFactory = context =>
{
var result = new BadRequestObjectResult(context.ModelState);
// TODO: add `using using System.Net.Mime;` to resolve MediaTypeNames
result.ContentTypes.Add(MediaTypeNames.Application.Json);
result.ContentTypes.Add(MediaTypeNames.Application.Xml);
return result;
};
});
İstemci hatası yanıtı
Hata sonucu, HTTP durum kodu 400 veya daha yüksek olan bir sonuç olarak tanımlanır. MVC, web API'si denetleyicileri için hata sonucundan ile bir sonuç ProblemDetails döndürür.
Önemli
ASP.NET Core 2.1, neredeyse RFC 7807 uyumlu bir sorun ayrıntıları yanıtı üretir. Yüzde 100 uyumluluk önemli ise projeyi 2.2 veya ASP.NET Core sürümüne yükseltin.
Hata yanıtı aşağıdaki yöntemlerden birini yapılandırabilirsiniz:
Uygulamak ProblemDetailsFactory
MVC, Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory tüm ve örneklerini üretmek için ProblemDetails ValidationProblemDetails kullanır. Buna istemci hatası yanıtları, doğrulama hatası yanıtları ve ControllerBase.Problem ve ControllerBase.ValidationProblem yardımcı yöntemleri dahildir.
Sorun ayrıntıları yanıtını özelleştirmek için içinde özel bir uygulamasını ProblemDetailsFactory Startup.ConfigureServices kaydettirin:
public void ConfigureServices(IServiceCollection serviceCollection)
{
services.AddControllers();
services.AddTransient<ProblemDetailsFactory, CustomProblemDetailsFactory>();
}
Hata yanıtı ApiBehaviorOptions.ClientErrorMapping kullanma bölümünde açıklanan şekilde yalıtılmış olabilir.
ApiBehaviorOptions.ClientErrorMapping kullanma
Yanıtın ClientErrorMapping içeriğini yapılandırmak için özelliğini ProblemDetails kullanın. Örneğin, içinde aşağıdaki kod Startup.ConfigureServices type 404 yanıtları için özelliğini günceller:
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";
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(options =>
{
options.SuppressConsumesConstraintForFormFileParameters = true;
options.SuppressInferBindingSourcesForParameters = true;
options.SuppressModelStateInvalidFilter = true;
options.SuppressMapClientErrors = true;
options.ClientErrorMapping[404].Link =
"https://httpstatuses.com/404";
});
Özel durumları işlemek için Özel Ara Yazılım
Özel durum işleme ara yazılımında varsayılanlar çoğu uygulama için iyi çalışır. Özelleştirilmiş özel durum işleme gerektiren uygulamalar için özel durum işleme ara yazılımlarını özelleştirmeyi göz önünde bulundurabilirsiniz.
Özel durumlar için ProblemDetails yükü üretme
ASP.NET Core, sunucu işlanmamış bir özel durumla karşılaştığında standartlaştırılmış bir hata yükü üretmez. İstemciye standartlaştırılmış bir ProblemDetails yanıtının geri dönmesi istenen senaryolarda, özel durumları ve 404'leri bir ProblemDetails yüküyle eşlemek için ProblemDetails ara yazılımı kullanılabilir. Özel durum işleme ara yazılımı, işlanmamış özel durumlar ProblemDetails için bir yük dönmek için de kullanılabilir.