Bagikan melalui


Menangani kesalahan di API inti ASP.NET

Nota

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 10 dari artikel ini.

Peringatan

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi lebih lanjut, lihat Kebijakan Dukungan .NET dan .NET Core . Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Artikel ini menjelaskan cara menangani kesalahan di ASP.NET Core API. Dokumentasi untuk API Minimal dipilih. Untuk melihat dokumentasi API berbasis pengontrol, pilih tab Pengontrol. Untuk Blazor panduan penanganan kesalahan, lihat Menangani kesalahan di aplikasi ASP.NET CoreBlazor.

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:

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 lingkungan runtime ASP.NET Core.

Halaman Pengecualian Pengembang dapat menyertakan informasi berikut tentang pengecualian dan permintaan:

  • Pelacakan tumpukan
  • Parameter string kueri, jika ada
  • Cookie, jika ada
  • Headers
  • 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:

Halaman pengecualian pengembang dianimasikan untuk menampilkan setiap tab yang dipilih.

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 di API Minimal:

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();

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 (400-499) 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):

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 menulis ProblemDetails. Misalnya, titik akhir di mana header Permintaan terima menentukan jenis media yang DefaulProblemDetailsWriter 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);

Fitur penanganan kesalahan tambahan

Migrasi dari pengontrol ke API Minimal

Jika Anda bermigrasi dari API berbasis pengontrol ke API Minimal:

  1. Mengganti filter tindakan dengan filter titik akhir atau middleware
  2. Ganti validasi model dengan validasi manual atau pengikatan kustom
  3. Ganti filter pengecualian dengan middleware penanganan pengecualian
  4. Mengonfigurasi detail masalah menggunakan AddProblemDetails() untuk respons kesalahan yang konsisten

Kapan menggunakan penanganan kesalahan berbasis pengontrol

Pertimbangkan API berbasis pengontrol jika Anda memerlukan:

  • Skenario validasi model kompleks
  • Penanganan pengecualian terpusat di beberapa pengontrol
  • Kontrol terperinci atas pemformatan respons kesalahan
  • Integrasi dengan fitur MVC seperti filter dan konvensi

Untuk informasi terperinci tentang penanganan kesalahan berbasis pengontrol, termasuk kesalahan validasi, kustomisasi detail masalah, dan filter pengecualian, lihat bagian tab Pengontrol .

Sumber daya tambahan