Cara menangani kesalahan di aplikasi API Minimal
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Dengan kontribusi oleh David Acker
Artikel ini menjelaskan cara menangani kesalahan di aplikasi API Minimal. Untuk informasi tentang penanganan kesalahan di API berbasis pengontrol, lihat Menangani kesalahan di kesalahan ASP.NET Core dan Menangani kesalahan di API web berbasis pengontrol Inti ASP.NET.
Pengecualian
Dalam aplikasi API Minimal, ada dua mekanisme terpusat bawaan yang berbeda untuk menangani pengecualian yang tidak tertangani:
- Middleware Halaman Pengecualian Pengembang (Hanya untuk digunakan di lingkungan Pengembangan.)
- Middleware handler pengecualian
Bagian ini mengacu pada aplikasi sampel berikut untuk menunjukkan cara menangani pengecualian dalam API Minimal. Ini melemparkan pengecualian ketika titik /exception
akhir diminta:
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();
Halaman Pengecualian Pengembang
Halaman Pengecualian Pengembang menampilkan informasi terperinci tentang pengecualian permintaan yang tidak tertangani. Ini menggunakan DeveloperExceptionPageMiddleware untuk menangkap pengecualian sinkron dan asinkron dari alur HTTP dan untuk menghasilkan respons kesalahan. Halaman pengecualian pengembang berjalan lebih awal di alur middleware, sehingga dapat menangkap pengecualian yang tidak tertangani yang dilemparkan dalam middleware yang mengikuti.
aplikasi ASP.NET Core mengaktifkan halaman pengecualian pengembang secara default saat keduanya:
- Berjalan di lingkungan Pengembangan.
- Aplikasi ini dibuat dengan templat saat ini, yaitu dengan menggunakan WebApplication.CreateBuilder.
Aplikasi yang dibuat menggunakan templat sebelumnya, yaitu, dengan menggunakan WebHost.CreateDefaultBuilder, dapat mengaktifkan halaman pengecualian pengembang dengan memanggil app.UseDeveloperExceptionPage
.
Peringatan
Jangan aktifkan Halaman Pengecualian Pengembang kecuali aplikasi berjalan di lingkungan Pengembangan. Jangan bagikan informasi pengecualian terperinci secara publik saat aplikasi berjalan dalam produksi. Untuk informasi selengkapnya tentang mengonfigurasi lingkungan, lihat Menggunakan beberapa lingkungan di ASP.NET Core.
Halaman Pengecualian Pengembang dapat menyertakan informasi berikut tentang pengecualian dan permintaan:
- Pelacakan tumpukan
- Parameter string kueri, jika ada
- Cookie, jika ada
- Header
- Metadata titik akhir, jika ada
Halaman Pengecualian Pengembang tidak dijamin untuk memberikan informasi apa pun. Gunakan Pengelogan untuk informasi kesalahan lengkap.
Gambar berikut menunjukkan contoh halaman pengecualian pengembang dengan animasi untuk memperlihatkan tab dan informasi yang ditampilkan:
Menanggapi permintaan dengan Accept: text/plain
header, Halaman Pengecualian Pengembang mengembalikan teks biasa alih-alih HTML. Contohnya:
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
Untuk melihat Halaman Pengecualian Pengembang:
- Jalankan aplikasi sampel di lingkungan Pengembangan.
/exception
Buka titik akhir.
Handler pengecualian
Di lingkungan non-pengembangan, gunakan Middleware Handler Pengecualian untuk menghasilkan payload kesalahan. Untuk mengonfigurasi Exception Handler Middleware
, panggil UseExceptionHandler.
Misalnya, kode berikut mengubah aplikasi untuk merespons dengan payload yang mematuhi RFC 7807 ke klien. Untuk informasi selengkapnya, lihat bagian Detail Masalah nanti di artikel ini.
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();
Respons kesalahan Klien dan Server
Pertimbangkan aplikasi API Minimal berikut.
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);
Titik /users
akhir menghasilkan 200 OK
dengan json
representasi User
kapan id
lebih besar dari 0
, jika tidak 400 BAD REQUEST
, kode status tanpa isi respons. Untuk informasi selengkapnya tentang membuat respons, lihat Membuat respons di aplikasi API Minimal.
Status Code Pages middleware
dapat dikonfigurasi untuk menghasilkan konten isi umum, ketika kosong, untuk semua respons klien HTTP (499
-400
) atau server ().500
-599
Middleware dikonfigurasi dengan memanggil metode ekstensi UseStatusCodePages .
Misalnya, contoh berikut mengubah aplikasi untuk merespons dengan payload yang mematuhi RFC 7807 ke klien untuk semua respons klien dan server, termasuk kesalahan perutean (misalnya, 404 NOT FOUND
). Untuk informasi selengkapnya, lihat bagian Detail Masalah.
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);
Detail masalah
Detail Masalah bukan satu-satunya format respons untuk menjelaskan kesalahan API HTTP, namun, biasanya digunakan untuk melaporkan kesalahan untuk API HTTP.
Layanan detail masalah mengimplementasikan IProblemDetailsService antarmuka, yang mendukung pembuatan detail masalah di ASP.NET Core. Metode AddProblemDetails(IServiceCollection) ekstensi pada IServiceCollection mendaftarkan implementasi default IProblemDetailsService
.
Di aplikasi ASP.NET Core, middleware berikut menghasilkan respons HTTP detail masalah saat AddProblemDetails
dipanggil, kecuali ketika Accept
header HTTP permintaan tidak menyertakan salah satu jenis konten yang didukung oleh yang terdaftar IProblemDetailsWriter (default: application/json
):
- ExceptionHandlerMiddleware: Menghasilkan respons detail masalah saat handler kustom tidak ditentukan.
- StatusCodePagesMiddleware: Menghasilkan respons detail masalah secara default.
- DeveloperExceptionPageMiddleware: Menghasilkan respons detail masalah dalam pengembangan ketika
Accept
header HTTP permintaan tidak menyertakantext/html
.
Aplikasi API minimal dapat dikonfigurasi untuk menghasilkan respons detail masalah untuk semua respons kesalahan klien HTTP dan server yang belum memiliki konten isi dengan menggunakan AddProblemDetails
metode ekstensi.
Kode berikut mengonfigurasi aplikasi untuk menghasilkan detail masalah:
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);
Untuk informasi selengkapnya tentang menggunakan AddProblemDetails
, lihat Detail Masalah
Fallback IProblemDetailsService
Dalam kode berikut, httpContext.Response.WriteAsync("Fallback: An error occurred.")
mengembalikan kesalahan jika IProblemDetailsService implementasi tidak dapat menghasilkan 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();
Kode sebelumnya:
- Menulis pesan kesalahan dengan kode fallback jika
problemDetailsService
tidak dapat menulisProblemDetails
. Misalnya, titik akhir di mana header Permintaan terima menentukan jenis media yangDefaulProblemDetailsWriter
tidak didukung. - Menggunakan Middleware Handler Pengecualian.
Sampel berikut mirip dengan sebelumnya kecuali bahwa ia memanggil 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);
Artikel ini menjelaskan cara menangani kesalahan di aplikasi API Minimal.
Pengecualian
Dalam aplikasi API Minimal, ada dua mekanisme terpusat bawaan yang berbeda untuk menangani pengecualian yang tidak tertangani:
- Middleware Halaman Pengecualian Pengembang (Hanya untuk digunakan di lingkungan Pengembangan.)
- Middleware handler pengecualian
Bagian ini mengacu pada aplikasi API Minimal berikut untuk menunjukkan cara menangani pengecualian. Ini melemparkan pengecualian ketika titik /exception
akhir diminta:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Halaman Pengecualian Pengembang
Halaman Pengecualian Pengembang memperlihatkan jejak tumpukan terperinci untuk kesalahan server. Ini menggunakan DeveloperExceptionPageMiddleware untuk menangkap pengecualian sinkron dan asinkron dari alur HTTP dan untuk menghasilkan respons kesalahan.
aplikasi ASP.NET Core mengaktifkan halaman pengecualian pengembang secara default saat keduanya:
- Berjalan di lingkungan Pengembangan.
- Aplikasi menggunakan WebApplication.CreateBuilder.
Untuk informasi selengkapnya tentang mengonfigurasi middleware, lihat Middleware di aplikasi API Minimal.
Menggunakan aplikasi API Minimal sebelumnya, ketika Developer Exception Page
mendeteksi pengecualian yang tidak tertangani, aplikasi menghasilkan respons teks biasa default yang mirip dengan contoh berikut:
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=utf-8
Date: Thu, 27 Oct 2022 18:00:59 GMT
Server: Kestrel
Transfer-Encoding: chunked
System.InvalidOperationException: Sample Exception
at Program.<>c.<<Main>$>b__0_1() in ....:line 17
at lambda_method2(Closure, Object, HttpContext)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
HEADERS
=======
Accept: */*
Connection: keep-alive
Host: localhost:5239
Accept-Encoding: gzip, deflate, br
Peringatan
Jangan aktifkan Halaman Pengecualian Pengembang kecuali aplikasi berjalan di lingkungan Pengembangan. Jangan bagikan informasi pengecualian terperinci secara publik saat aplikasi berjalan dalam produksi. Untuk informasi selengkapnya tentang mengonfigurasi lingkungan, lihat Menggunakan beberapa lingkungan di ASP.NET Core.
Handler pengecualian
Di lingkungan non-pengembangan, gunakan Middleware Handler Pengecualian untuk menghasilkan payload kesalahan. Untuk mengonfigurasi Exception Handler Middleware
, panggil UseExceptionHandler.
Misalnya, kode berikut mengubah aplikasi untuk merespons dengan payload yang mematuhi RFC 7807 ke klien. Untuk informasi selengkapnya, lihat bagian Detail Masalah.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseExceptionHandler(exceptionHandlerApp
=> exceptionHandlerApp.Run(async context
=> await Results.Problem()
.ExecuteAsync(context)));
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Respons kesalahan Klien dan Server
Pertimbangkan aplikasi API Minimal berikut.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Run();
public record User(int Id);
Titik /users
akhir menghasilkan 200 OK
dengan json
representasi User
kapan id
lebih besar dari 0
, jika tidak 400 BAD REQUEST
, kode status tanpa isi respons. Untuk informasi selengkapnya tentang membuat respons, lihat Membuat respons di aplikasi API Minimal.
Status Code Pages middleware
dapat dikonfigurasi untuk menghasilkan konten isi umum, ketika kosong, untuk semua respons klien HTTP (499
-400
) atau server ().500
-599
Middleware dikonfigurasi dengan memanggil metode ekstensi UseStatusCodePages .
Misalnya, contoh berikut mengubah aplikasi untuk merespons dengan payload yang mematuhi RFC 7807 ke klien untuk semua respons klien dan server, termasuk kesalahan perutean (misalnya, 404 NOT FOUND
). Untuk informasi selengkapnya, lihat bagian Detail Masalah.
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.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Run();
public record User(int Id);
Detail masalah
Detail Masalah bukan satu-satunya format respons untuk menjelaskan kesalahan API HTTP, namun, biasanya digunakan untuk melaporkan kesalahan untuk API HTTP.
Layanan detail masalah mengimplementasikan IProblemDetailsService antarmuka, yang mendukung pembuatan detail masalah di ASP.NET Core. Metode AddProblemDetails(IServiceCollection) ekstensi pada IServiceCollection mendaftarkan implementasi default IProblemDetailsService
.
Di aplikasi ASP.NET Core, middleware berikut menghasilkan respons HTTP detail masalah saat AddProblemDetails
dipanggil, kecuali ketika Accept
header HTTP permintaan tidak menyertakan salah satu jenis konten yang didukung oleh yang terdaftar IProblemDetailsWriter (default: application/json
):
- ExceptionHandlerMiddleware: Menghasilkan respons detail masalah saat handler kustom tidak ditentukan.
- StatusCodePagesMiddleware: Menghasilkan respons detail masalah secara default.
- DeveloperExceptionPageMiddleware: Menghasilkan respons detail masalah dalam pengembangan ketika
Accept
header HTTP permintaan tidak menyertakantext/html
.
Aplikasi API minimal dapat dikonfigurasi untuk menghasilkan respons detail masalah untuk semua respons kesalahan klien HTTP dan server yang belum memiliki konten isi dengan menggunakan AddProblemDetails
metode ekstensi.
Kode berikut mengonfigurasi aplikasi untuk menghasilkan detail masalah:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
app.UseExceptionHandler();
app.UseStatusCodePages();
app.Map("/users/{id:int}", (int id)
=> id <= 0 ? Results.BadRequest() : Results.Ok(new User(id)) );
app.Map("/exception", ()
=> { throw new InvalidOperationException("Sample Exception"); });
app.Run();
Untuk informasi selengkapnya tentang menggunakan AddProblemDetails
, lihat Detail Masalah
ASP.NET Core