Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Note
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 10 dari artikel ini.
Warning
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 9 dari artikel ini.
Artikel ini membahas pendekatan umum untuk menangani kesalahan di aplikasi web ASP.NET Core. Lihat juga Menangani kesalahan di API inti ASP.NET.
Untuk panduan penanganan kesalahan Blazor, yang menambahkan atau menggantikan panduan dalam artikel ini, lihat Handle errors in ASP.NET Core Blazor apps.
Halaman pengecualian pengembang perangkat lunak
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 pipeline middleware, sehingga dapat menangkap pengecualian yang tidak tertangani yang dilemparkan oleh middleware berikutnya.
Aplikasi ASP.NET Core secara default mengaktifkan halaman pengecualian pengembang saat kedua kondisi berikut terpenuhi:
- 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.
Warning
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:
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
Halaman penanganan pengecualian
Untuk mengonfigurasi halaman penanganan kesalahan kustom untuk lingkungan Produksi, panggil UseExceptionHandler. Middleware penanganan pengecualian ini:
- Menangkap dan mencatat pengecualian yang tidak tertangani.
- Menjalankan kembali permintaan dalam alur alternatif menggunakan jalur yang ditunjukkan. Permintaan tidak dijalankan kembali jika respons telah dimulai. Kode yang dihasilkan templat menjalankan kembali permintaan menggunakan
/Errorjalur .
Warning
Jika alur alternatif menghasilkan pengecualian miliknya, Exception Handling Middleware akan memunculkan kembali pengecualian asli.
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - UseExceptionHandler(IApplicationBuilder, String) Untuk kelebihan beban yang digunakan dalam templat, hanya jalur permintaan yang dimodifikasi, dan data rute dibersihkan. Data permintaan seperti header, metode, dan item semuanya digunakan kembali apa adanya.
- Layanan terlingkup tetap sama.
Dalam contoh berikut, UseExceptionHandler menambahkan middleware penanganan pengecualian di lingkungan selain Pengembangan.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Templat aplikasi Pages menyediakan halaman kesalahan (Razor) dan kelas (.cshtml) di PageModel. Untuk aplikasi MVC, templat proyek menyertakan Error metode tindakan dan tampilan Kesalahan untuk Home pengontrol.
Middleware penanganan pengecualian menjalankan kembali permintaan menggunakan metode HTTP asli . Jika sebuah endpoint handler kesalahan dibatasi hanya untuk sekumpulan metode HTTP tertentu, maka endpoint tersebut hanya akan berjalan untuk metode HTTP tersebut. Misalnya, tindakan pengontrol MVC yang menggunakan [HttpGet] atribut hanya berjalan untuk permintaan GET. Untuk memastikan bahwa semua permintaan mencapai halaman penanganan kesalahan kustom, jangan batasi ke sekumpulan metode HTTP tertentu.
Untuk menangani pengecualian secara berbeda berdasarkan metode HTTP asli:
- Untuk Razor Pages, buat beberapa metode handler. Misalnya, gunakan
OnGetuntuk menangani pengecualian GET dan gunakanOnPostuntuk menangani pengecualian POST. - Untuk MVC, terapkan atribut kata kerja HTTP ke beberapa tindakan. Misalnya, gunakan
[HttpGet]untuk menangani pengecualian GET dan gunakan[HttpPost]untuk menangani pengecualian POST.
Untuk mengizinkan pengguna yang tidak terautentikasi untuk melihat halaman penanganan kesalahan kustom, pastikan halaman tersebut mendukung akses anonim.
Mengakses pengecualian
Gunakan IExceptionHandlerPathFeature untuk mengakses pengecualian dan jalur permintaan asli dalam penangan kesalahan. Contoh berikut menggunakan IExceptionHandlerPathFeature untuk mendapatkan informasi selengkapnya tentang pengecualian yang dilemparkan:
[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.";
}
}
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Penangan pengecualian lambda
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan sebelum mengembalikan respons.
Kode berikut menggunakan lambda untuk penanganan pengecualian:
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();
}
Cara lain untuk menggunakan lambda adalah dengan mengatur kode status berdasarkan jenis pengecualian, seperti dalam contoh berikut:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseExceptionHandler(new ExceptionHandlerOptions
{
StatusCodeSelector = ex => ex is TimeoutException
? StatusCodes.Status503ServiceUnavailable
: StatusCodes.Status500InternalServerError
});
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
IExceptionHandler
IExceptionHandler adalah antarmuka yang memberi pengembang panggilan balik untuk menangani pengecualian yang diketahui di lokasi pusat. Antarmuka berisi satu metode, TryHandleAsync, yang menerima parameter HttpContext dan .Exception
IExceptionHandler implementasi didaftarkan dengan memanggil IServiceCollection.AddExceptionHandler<T>. Masa hidup instans IExceptionHandler adalah singleton. Beberapa implementasi dapat ditambahkan, dan dipanggil dalam urutan terdaftar.
Penanganan pengecualian middleware berulang melalui handler pengecualian terdaftar secara berurutan sampai satu mengembalikan true dari TryHandleAsync, yang menunjukkan bahwa pengecualian telah ditangani. Jika handler pengecualian menangani pengecualian, handler tersebut dapat mengembalikan true untuk menghentikan pemrosesan. Jika pengecualian tidak ditangani oleh handler pengecualian apa pun, kontrol akan kembali ke perilaku dan opsi default dari middleware.
Mulai dari .NET 10, perilaku defaultnya adalah menekan emisi diagnostik seperti log dan metrik untuk pengecualian yang ditangani (saat TryHandleAsync mengembalikan true). Ini berbeda dari versi sebelumnya (.NET 8 dan 9) di mana diagnostik selalu dipancarkan terlepas dari apakah pengecualian ditangani. Perilaku default dapat diubah dengan mengatur SuppressDiagnosticsCallback.
Contoh berikut menunjukkan implementasi IExceptionHandler:
using Microsoft.AspNetCore.Diagnostics;
namespace ErrorHandlingSample
{
public class CustomExceptionHandler : IExceptionHandler
{
private readonly ILogger<CustomExceptionHandler> logger;
public CustomExceptionHandler(ILogger<CustomExceptionHandler> logger)
{
this.logger = logger;
}
public ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
var exceptionMessage = exception.Message;
logger.LogError(
"Error Message: {exceptionMessage}, Time of occurrence {time}",
exceptionMessage, DateTime.UtcNow);
// Return false to continue with the default behavior
// - or - return true to signal that this exception is handled
return ValueTask.FromResult(false);
}
}
}
Contoh berikut menunjukkan cara mendaftarkan IExceptionHandler implementasi untuk injeksi dependensi:
using ErrorHandlingSample;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
builder.Services.AddExceptionHandler<CustomExceptionHandler>();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
// Remaining Program.cs code omitted for brevity
Saat kode sebelumnya berjalan di lingkungan Pengembangan:
- dipanggil
CustomExceptionHandlerterlebih dahulu untuk menangani pengecualian. - Setelah mencatat pengecualian,
TryHandleAsyncmetode mengembalikanfalse, sehingga halaman pengecualian pengembang ditampilkan.
Di lingkungan lain:
- dipanggil
CustomExceptionHandlerterlebih dahulu untuk menangani pengecualian. - Setelah mencatat pengecualian,
TryHandleAsyncmetode mengembalikanfalse, sehingga/Errorhalaman ditampilkan.
SuppressDiagnosticsCallback
Mulai dengan .NET 10, Anda dapat mengontrol apakah middleware penanganan pengecualian menghasilkan pesan diagnostik untuk pengecualian yang ditangani dengan mengonfigurasi properti SuppressDiagnosticsCallback pada ExceptionHandlerOptions. Callback ini menerima konteks pengecualian dan memungkinkan Anda menentukan apakah diagnosis harus dihilangkan berdasarkan pada pengecualian atau permintaan yang spesifik.
**
Untuk kembali ke perilaku .NET 8 dan 9 di mana diagnostik selalu dihasilkan untuk pengecualian yang ditangani, atur panggilan balik agar selalu mengembalikan false:
app.UseExceptionHandler(new ExceptionHandlerOptions
{
SuppressDiagnosticsCallback = context => false
});
Anda juga dapat secara kondisional menekan diagnostik berdasarkan jenis pengecualian atau konteks lainnya:
app.UseExceptionHandler(new ExceptionHandlerOptions
{
SuppressDiagnosticsCallback = context => context.Exception is ArgumentException
});
Ketika pengecualian tidak ditangani oleh implementasi apa pun IExceptionHandler (semua handler kembali false dari TryHandleAsync), kontrol kembali ke perilaku dan opsi default dari middleware, dan diagnostik dipancarkan sesuai dengan perilaku standar middleware.
UseStatusCodePages
Secara default, aplikasi ASP.NET Core tidak menyediakan halaman kode status untuk kode status kesalahan HTTP, seperti 404 - Tidak Ditemukan. Saat aplikasi menetapkan kode status kesalahan HTTP 400-599 yang tidak memiliki isi, aplikasi mengembalikan kode status dan isi respons kosong. Untuk mengaktifkan handler teks saja sebagai default untuk kode status error umum, panggil UseStatusCodePages di Program.cs:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Panggil UseStatusCodePages sebelum meminta penanganan middleware. Misalnya, panggil UseStatusCodePages sebelum Static File Middleware dan Endpoints Middleware.
Saat UseStatusCodePages tidak digunakan, menavigasi ke URL tanpa titik akhir mengembalikan pesan kesalahan yang bergantung pada browser yang menunjukkan titik akhir tidak dapat ditemukan. Ketika UseStatusCodePages dipanggil, browser mengembalikan respons berikut:
Status Code: 404; Not Found
UseStatusCodePages biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak berguna bagi pengguna.
Note
Halaman kode status middleware tidak menangkap pengecualian. Untuk menyediakan halaman penanganan kesalahan khusus, gunakan halaman handler pengecualian.
GunakanStatusCodePages dengan string format
Untuk mengustomisasi tipe konten dan teks respons, gunakan versi overload dari UseStatusCodePages yang menerima tipe konten dan string format:
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}");
Dalam kode sebelumnya, {0} adalah tempat penampung untuk kode kesalahan.
UseStatusCodePages dengan string format biasanya tidak digunakan dalam produksi karena menampilkan pesan yang tidak berguna bagi pengguna.
Gunakan StatusCodePages dengan lambda
Untuk menentukan penanganan kesalahan kustom dan kode penulisan respons, gunakan kelebihan beban UseStatusCodePages yang mengambil ekspresi 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 dengan lambda biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak memberikan manfaat bagi pengguna.
UseStatusCodePagesWithRedirects
Metode ekstensi UseStatusCodePagesWithRedirects
- Mengirim kode status 302 - Ditemukan ke klien.
- Mengalihkan klien ke titik akhir penanganan kesalahan yang disediakan dalam templat URL. Titik akhir penanganan kesalahan biasanya menampilkan informasi kesalahan dan mengembalikan HTTP 200.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Templat URL dapat menyertakan {0} sebagai penampung untuk kode status, sesuai yang ditunjukkan dalam kode sebelumnya. Jika templat URL dimulai dengan ~ (tilde), ~ digantikan oleh PathBase milik aplikasi. Saat menentukan titik akhir di aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan saat aplikasi:
- Harus mengalihkan klien ke titik akhir yang berbeda, biasanya dalam kasus di mana aplikasi yang berbeda memproses kesalahan. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang dialihkan.
- Tidak seharusnya mempertahankan dan mengembalikan kode status asli saat memberikan respons pengalihan awal.
UseStatusCodePagesWithReExecute
Metode ekstensi UseStatusCodePagesWithReExecute
- Menghasilkan isi respons dengan mengeksekusi ulang alur permintaan menggunakan jalur alternatif.
- Tidak mengubah kode status, baik sebelum maupun sesudah menjalankan ulang alurnya.
Eksekusi alur baru dapat mengubah kode status respons, karena alur baru memiliki kontrol penuh atas kode status. Jika alur baru tidak mengubah kode status, kode status asli akan dikirim ke klien.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Jika titik akhir dalam aplikasi ditentukan, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan ketika aplikasi harus:
- Proses permintaan tanpa mengalihkan ke titik akhir yang berbeda. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang awalnya diminta.
- Pertahankan dan kembalikan kode status asli dengan respons.
Templat URL harus dimulai dengan / dan dapat menyertakan tempat penampung {0} untuk kode status. Untuk meneruskan kode status sebagai parameter string kueri, teruskan argumen kedua ke dalam UseStatusCodePagesWithReExecute. Contohnya:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
Titik akhir yang memproses kesalahan bisa mendapatkan URL asli yang menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
[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 = $"{statusCodeReExecuteFeature.OriginalPathBase}"
+ $"{statusCodeReExecuteFeature.OriginalPath}"
+ $"{statusCodeReExecuteFeature.OriginalQueryString}";
}
}
}
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - Layanan terlingkup tetap sama.
Menonaktifkan halaman kode status
Untuk menonaktifkan halaman kode status untuk pengontrol MVC atau metode tindakan, gunakan atribut [SkipStatusCodePages ].
Untuk menonaktifkan halaman kode status untuk permintaan tertentu dalam Razor metode handler Pages atau di pengontrol MVC, gunakan IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kode penanganan pengecualian
Kode dalam halaman penanganan pengecualian juga dapat melemparkan pengecualian. Halaman kesalahan produksi harus diuji secara menyeluruh dan berhati-hatilah untuk menghindari melempar pengecualian sendiri.
Tajuk respons
Setelah header untuk respons dikirim:
- Aplikasi tidak dapat mengubah kode status respons.
- Halaman pengecualian atau handler apa pun tidak dapat dijalankan. Respons harus diselesaikan atau koneksi dibatalkan.
Penanganan pengecualian server
Selain logika penanganan pengecualian dalam aplikasi, implementasi server HTTP dapat menangani beberapa pengecualian. Jika server menangkap pengecualian sebelum header respons dikirim, server mengirim 500 - Internal Server Error respons tanpa isi respons. Jika server menangkap pengecualian setelah header respons dikirim, server menutup koneksi. Permintaan yang tidak ditangani oleh aplikasi ditangani oleh server. Pengecualian apa pun yang terjadi ketika server menangani permintaan ditangani oleh penanganan pengecualian server. Halaman kesalahan kustom aplikasi, middleware penanganan pengecualian, dan filter tidak memengaruhi perilaku ini.
Penanganan pengecualian startup
Hanya lapisan hosting yang dapat menangani pengecualian yang terjadi selama startup aplikasi. Host dapat dikonfigurasi untuk menangkap kesalahan pada saat startup dan menangkap kesalahan yang terperinci.
Lapisan hosting dapat menampilkan halaman kesalahan untuk kesalahan startup yang terdeteksi hanya jika kesalahan terjadi setelah pengikatan alamat dan port host. Jika pengikatan gagal:
- Lapisan hosting mencatat pengecualian penting.
- Proses dotnet mengalami crash.
- Tidak ada halaman kesalahan yang ditampilkan ketika server HTTP adalah Kestrel.
Saat berjalan di IIS (atau Azure App Service) atau IIS Express, 502.5 - Kegagalan Proses dikembalikan oleh Modul ASP.NET Core jika proses tidak dapat dimulai. Untuk informasi selengkapnya, lihat Memecahkan masalah ASP.NET Core di Azure App Service dan IIS.
Halaman kesalahan database
Filter pengecualian halaman pengembang basis data AddDatabaseDeveloperPageExceptionFilter menangkap pengecualian terkait basis data yang dapat diselesaikan dengan migrasi Entity Framework Core. Ketika pengecualian ini terjadi, respons HTML dihasilkan dengan detail kemungkinan tindakan untuk menyelesaikan masalah. Halaman ini hanya diaktifkan di lingkungan Pengembangan. Kode berikut menambahkan filter pengecualian untuk halaman pengembang basis data:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Filter pengecualian
Di aplikasi MVC, filter pengecualian dapat dikonfigurasi secara global atau berdasarkan per pengontrol atau per tindakan. Di Razor aplikasi Pages, aplikasi tersebut dapat dikonfigurasi secara global atau per model halaman. Filter ini menangani pengecualian yang tidak tertangani yang terjadi selama eksekusi tindakan pengontrol atau filter lain. Untuk informasi selengkapnya, lihat Filter di ASP.NET Core.
Filter pengecualian berguna untuk menjebak pengecualian yang terjadi dalam tindakan MVC, tetapi tidak fleksibel seperti middleware penanganan pengecualian bawaan, UseExceptionHandler. Sebaiknya gunakan UseExceptionHandler, kecuali Anda perlu melakukan penanganan kesalahan secara berbeda berdasarkan tindakan MVC mana yang dipilih.
Kesalahan status model
Untuk informasi tentang cara menangani kesalahan status model, lihat Pengikatan model dan Validasi model.
Detail masalah
Rincian Masalah bukan satu-satunya format respons untuk menggambarkan kesalahan pada API HTTP, tetapi format ini biasanya digunakan untuk melaporkan kesalahan pada 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 header HTTP
Acceptpermintaan tidak menyertakantext/html.
Kode berikut mengonfigurasi aplikasi untuk menghasilkan respons detail masalah untuk semua respons kesalahan klien HTTP dan server yang belum memiliki konten isi:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Bagian berikutnya memperlihatkan cara menyesuaikan isi respons detail masalah.
Menyesuaikan detail masalah
Pembuatan ProblemDetails otomatis dapat dikustomisasi menggunakan salah satu opsi berikut:
- Menggunakan
ProblemDetailsOptions.CustomizeProblemDetails - Gunakan kustom
IProblemDetailsWriter -
IProblemDetailsServiceMemanggil di middleware
CustomizeProblemDetails operasi
Detail masalah yang dihasilkan dapat disesuaikan menggunakan CustomizeProblemDetails, dan kustomisasi diterapkan ke semua detail masalah yang dihasilkan secara otomatis.
Kode berikut menggunakan ProblemDetailsOptions untuk mengatur CustomizeProblemDetails:
builder.Services.AddProblemDetails(options =>
options.CustomizeProblemDetails = ctx =>
ctx.ProblemDetails.Extensions.Add("nodeId", Environment.MachineName));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Misalnya, HTTP Status 400 Bad Request hasil titik akhir menghasilkan isi respons detail masalah berikut:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Kustom IProblemDetailsWriter
Implementasi IProblemDetailsWriter dapat dibuat untuk kustomisasi tingkat lanjut.
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));
}
}
Catatan: Saat menggunakan kustom IProblemDetailsWriter, kustom IProblemDetailsWriter harus didaftarkan sebelum memanggil AddRazorPages, , AddControllers, AddControllersWithViewsatau AddMvc:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTransient<IProblemDetailsWriter, SampleProblemDetailsWriter>();
var app = builder.Build();
// 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<IProblemDetailsWriter>() is
{ } problemDetailsService)
{
if (problemDetailsService.CanWrite(new ProblemDetailsContext() { HttpContext = context }))
{
(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.Run();
Detail masalah dari Middleware
Pendekatan alternatif untuk menggunakan ProblemDetailsOptions dengan CustomizeProblemDetails adalah mengatur ProblemDetails di middleware. Respons detail masalah dapat ditulis dengan memanggil 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();
Dalam kode sebelumnya, endpoint API minimal /divide dan /squareroot mengembalikan respons masalah kustom yang diharapkan ketika ada input yang salah.
Titik akhir pengontrol API mengembalikan respons masalah default pada input kesalahan, bukan respons masalah kustom. Respons masalah default dikembalikan karena pengontrol API telah menulis ke aliran respons, Detail masalah untuk kode status error, sebelum IProblemDetailsService.WriteAsync dipanggil, sehingga respons tidak ditulis lagi.
Berikut ini ValuesController mengembalikan BadRequestResult, yang menulis ke aliran respons dan oleh karena itu mencegah respons masalah kustom dikembalikan.
[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));
}
}
Berikut ini Values3Controller mengembalikan ControllerBase.Problem sehingga hasil masalah kustom yang diharapkan dikembalikan:
[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));
}
}
Menghasilkan payload ProblemDetails untuk pengecualian
Pertimbangkan aplikasi berikut:
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();
Di lingkungan non-pengembangan, ketika pengecualian terjadi, berikut ini adalah respons ProblemDetails standar yang dikembalikan ke klien:
{
"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"
}
Untuk sebagian besar aplikasi, kode sebelumnya adalah semua yang diperlukan untuk pengecualian. Namun, bagian berikut menunjukkan cara mendapatkan respons masalah yang lebih rinci.
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan dan menulis respons detail masalah dengan 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 = "Argument exception";
detail = "Invalid input";
type = "https://errors.example.com/argumentException";
}
await problemDetailsService.WriteAsync(new ProblemDetailsContext
{
HttpContext = context,
ProblemDetails =
{
Title = title,
Detail = detail,
Type = type
}
});
}
});
});
}
app.MapControllers();
app.Run();
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Pendekatan alternatif untuk menghasilkan detail masalah adalah menggunakan paket NuGet pihak ketiga Hellang.Middleware.ProblemDetails yang dapat digunakan untuk memetakan pengecualian dan kesalahan klien ke detail masalah.
Sumber daya tambahan
- Melihat atau mengunduh kode sampel (cara mengunduh)
- Memecahkan masalah ASP.NET Core pada Azure App Service dan IIS
- Pemecahan masalah kesalahan umum untuk Azure App Service dan IIS dengan ASP.NET Core
- Menangani kesalahan di API inti ASP.NET
-
Perubahan yang melanggar: Diagnostik pengecualian ditekan saat
IExceptionHandler.TryHandleAsyncmengembalikan true
Artikel ini membahas pendekatan umum untuk menangani kesalahan di aplikasi web ASP.NET Core. Lihat juga Menangani kesalahan di API inti ASP.NET.
Untuk panduan penanganan kesalahan Blazor, yang menambahkan atau menggantikan panduan dalam artikel ini, lihat Handle errors in ASP.NET Core Blazor apps.
Halaman pengecualian pengembang perangkat lunak
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 pipeline middleware, sehingga dapat menangkap pengecualian yang tidak tertangani yang dilemparkan oleh middleware berikutnya.
Aplikasi ASP.NET Core secara default mengaktifkan halaman pengecualian pengembang saat kedua kondisi berikut terpenuhi:
- 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.
Warning
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:
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
Halaman penanganan pengecualian
Untuk mengonfigurasi halaman penanganan kesalahan kustom untuk lingkungan Produksi, panggil UseExceptionHandler. Middleware penanganan pengecualian ini:
- Menangkap dan mencatat pengecualian yang tidak tertangani.
- Menjalankan kembali permintaan dalam alur alternatif menggunakan jalur yang ditunjukkan. Permintaan tidak dijalankan kembali jika respons telah dimulai. Kode yang dihasilkan templat menjalankan kembali permintaan menggunakan
/Errorjalur .
Warning
Jika alur alternatif menghasilkan pengecualian miliknya, Exception Handling Middleware akan memunculkan kembali pengecualian asli.
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - UseExceptionHandler(IApplicationBuilder, String) Untuk kelebihan beban yang digunakan dalam templat, hanya jalur permintaan yang dimodifikasi, dan data rute dibersihkan. Data permintaan seperti header, metode, dan item semuanya digunakan kembali apa adanya.
- Layanan terlingkup tetap sama.
Dalam contoh berikut, UseExceptionHandler menambahkan middleware penanganan pengecualian di lingkungan selain Pengembangan.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Templat aplikasi Pages menyediakan halaman kesalahan (Razor) dan kelas (.cshtml) di PageModel. Untuk aplikasi MVC, templat proyek menyertakan Error metode tindakan dan tampilan Kesalahan untuk Home pengontrol.
Middleware penanganan pengecualian menjalankan kembali permintaan menggunakan metode HTTP asli . Jika sebuah endpoint handler kesalahan dibatasi hanya untuk sekumpulan metode HTTP tertentu, maka endpoint tersebut hanya akan berjalan untuk metode HTTP tersebut. Misalnya, tindakan pengontrol MVC yang menggunakan [HttpGet] atribut hanya berjalan untuk permintaan GET. Untuk memastikan bahwa semua permintaan mencapai halaman penanganan kesalahan kustom, jangan batasi ke sekumpulan metode HTTP tertentu.
Untuk menangani pengecualian secara berbeda berdasarkan metode HTTP asli:
- Untuk Razor Pages, buat beberapa metode handler. Misalnya, gunakan
OnGetuntuk menangani pengecualian GET dan gunakanOnPostuntuk menangani pengecualian POST. - Untuk MVC, terapkan atribut kata kerja HTTP ke beberapa tindakan. Misalnya, gunakan
[HttpGet]untuk menangani pengecualian GET dan gunakan[HttpPost]untuk menangani pengecualian POST.
Untuk mengizinkan pengguna yang tidak terautentikasi untuk melihat halaman penanganan kesalahan kustom, pastikan halaman tersebut mendukung akses anonim.
Mengakses pengecualian
Gunakan IExceptionHandlerPathFeature untuk mengakses pengecualian dan jalur permintaan asli dalam penangan kesalahan. Contoh berikut menggunakan IExceptionHandlerPathFeature untuk mendapatkan informasi selengkapnya tentang pengecualian yang dilemparkan:
[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.";
}
}
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Penangan pengecualian lambda
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan sebelum mengembalikan respons.
Kode berikut menggunakan lambda untuk penanganan pengecualian:
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();
}
Cara lain untuk menggunakan lambda adalah dengan mengatur kode status berdasarkan jenis pengecualian, seperti dalam contoh berikut:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddProblemDetails();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseExceptionHandler(new ExceptionHandlerOptions
{
StatusCodeSelector = ex => ex is TimeoutException
? StatusCodes.Status503ServiceUnavailable
: StatusCodes.Status500InternalServerError
});
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
IExceptionHandler
IExceptionHandler adalah antarmuka yang memberi pengembang panggilan balik untuk menangani pengecualian yang diketahui di lokasi pusat.
IExceptionHandler implementasi didaftarkan dengan memanggil IServiceCollection.AddExceptionHandler<T>. Masa hidup instans IExceptionHandler adalah singleton. Beberapa implementasi dapat ditambahkan, dan dipanggil dalam urutan terdaftar.
Jika handler pengecualian menangani permintaan, handler dapat mengembalikan true untuk menghentikan pemrosesan. Jika pengecualian tidak ditangani oleh handler pengecualian apa pun, kontrol akan kembali ke perilaku dan opsi default dari middleware. Metrik dan log yang berbeda dipancarkan untuk pengecualian yang ditangani versus pengecualian yang tidak tertangani.
Contoh berikut menunjukkan implementasi IExceptionHandler:
using Microsoft.AspNetCore.Diagnostics;
namespace ErrorHandlingSample
{
public class CustomExceptionHandler : IExceptionHandler
{
private readonly ILogger<CustomExceptionHandler> logger;
public CustomExceptionHandler(ILogger<CustomExceptionHandler> logger)
{
this.logger = logger;
}
public ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
var exceptionMessage = exception.Message;
logger.LogError(
"Error Message: {exceptionMessage}, Time of occurrence {time}",
exceptionMessage, DateTime.UtcNow);
// Return false to continue with the default behavior
// - or - return true to signal that this exception is handled
return ValueTask.FromResult(false);
}
}
}
Contoh berikut menunjukkan cara mendaftarkan IExceptionHandler implementasi untuk injeksi dependensi:
using ErrorHandlingSample;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
builder.Services.AddExceptionHandler<CustomExceptionHandler>();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
// Remaining Program.cs code omitted for brevity
Saat kode sebelumnya berjalan di lingkungan Pengembangan:
- dipanggil
CustomExceptionHandlerterlebih dahulu untuk menangani pengecualian. - Setelah mencatat pengecualian,
TryHandleAsyncmetode mengembalikanfalse, sehingga halaman pengecualian pengembang ditampilkan.
Di lingkungan lain:
- dipanggil
CustomExceptionHandlerterlebih dahulu untuk menangani pengecualian. - Setelah mencatat pengecualian,
TryHandleAsyncmetode mengembalikanfalse, sehingga/Errorhalaman ditampilkan.
UseStatusCodePages
Secara default, aplikasi ASP.NET Core tidak menyediakan halaman kode status untuk kode status kesalahan HTTP, seperti 404 - Tidak Ditemukan. Saat aplikasi menetapkan kode status kesalahan HTTP 400-599 yang tidak memiliki isi, aplikasi mengembalikan kode status dan isi respons kosong. Untuk mengaktifkan handler teks saja sebagai default untuk kode status error umum, panggil UseStatusCodePages di Program.cs:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Panggil UseStatusCodePages sebelum meminta penanganan middleware. Misalnya, panggil UseStatusCodePages sebelum Static File Middleware dan Endpoints Middleware.
Saat UseStatusCodePages tidak digunakan, menavigasi ke URL tanpa titik akhir mengembalikan pesan kesalahan yang bergantung pada browser yang menunjukkan titik akhir tidak dapat ditemukan. Ketika UseStatusCodePages dipanggil, browser mengembalikan respons berikut:
Status Code: 404; Not Found
UseStatusCodePages biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak berguna bagi pengguna.
Note
Halaman kode status middleware tidak menangkap pengecualian. Untuk menyediakan halaman penanganan kesalahan khusus, gunakan halaman handler pengecualian.
GunakanStatusCodePages dengan string format
Untuk mengustomisasi tipe konten dan teks respons, gunakan versi overload dari UseStatusCodePages yang menerima tipe konten dan string format:
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}");
Dalam kode sebelumnya, {0} adalah tempat penampung untuk kode kesalahan.
UseStatusCodePages dengan string format biasanya tidak digunakan dalam produksi karena menampilkan pesan yang tidak berguna bagi pengguna.
Gunakan StatusCodePages dengan lambda
Untuk menentukan penanganan kesalahan kustom dan kode penulisan respons, gunakan kelebihan beban UseStatusCodePages yang mengambil ekspresi 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 dengan lambda biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak memberikan manfaat bagi pengguna.
UseStatusCodePagesWithRedirects
Metode ekstensi UseStatusCodePagesWithRedirects
- Mengirim kode status 302 - Ditemukan ke klien.
- Mengalihkan klien ke titik akhir penanganan kesalahan yang disediakan dalam templat URL. Titik akhir penanganan kesalahan biasanya menampilkan informasi kesalahan dan mengembalikan HTTP 200.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Templat URL dapat menyertakan {0} sebagai penampung untuk kode status, sesuai yang ditunjukkan dalam kode sebelumnya. Jika templat URL dimulai dengan ~ (tilde), ~ digantikan oleh PathBase milik aplikasi. Saat menentukan titik akhir di aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan saat aplikasi:
- Harus mengalihkan klien ke titik akhir yang berbeda, biasanya dalam kasus di mana aplikasi yang berbeda memproses kesalahan. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang dialihkan.
- Tidak seharusnya mempertahankan dan mengembalikan kode status asli saat memberikan respons pengalihan awal.
UseStatusCodePagesWithReExecute
Metode ekstensi UseStatusCodePagesWithReExecute
- Menghasilkan isi respons dengan mengeksekusi ulang alur permintaan menggunakan jalur alternatif.
- Tidak mengubah kode status, baik sebelum maupun sesudah menjalankan ulang alurnya.
Eksekusi alur baru dapat mengubah kode status respons, karena alur baru memiliki kontrol penuh atas kode status. Jika alur baru tidak mengubah kode status, kode status asli akan dikirim ke klien.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Jika titik akhir dalam aplikasi ditentukan, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan ketika aplikasi harus:
- Proses permintaan tanpa mengalihkan ke titik akhir yang berbeda. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang awalnya diminta.
- Pertahankan dan kembalikan kode status asli dengan respons.
Templat URL harus dimulai dengan / dan dapat menyertakan tempat penampung {0} untuk kode status. Untuk meneruskan kode status sebagai parameter string kueri, teruskan argumen kedua ke dalam UseStatusCodePagesWithReExecute. Contohnya:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
Titik akhir yang memproses kesalahan bisa mendapatkan URL asli yang menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
[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 = $"{statusCodeReExecuteFeature.OriginalPathBase}"
+ $"{statusCodeReExecuteFeature.OriginalPath}"
+ $"{statusCodeReExecuteFeature.OriginalQueryString}";
}
}
}
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - Layanan terlingkup tetap sama.
Menonaktifkan halaman kode status
Untuk menonaktifkan halaman kode status untuk pengontrol MVC atau metode tindakan, gunakan atribut [SkipStatusCodePages ].
Untuk menonaktifkan halaman kode status untuk permintaan tertentu dalam Razor metode handler Pages atau di pengontrol MVC, gunakan IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kode penanganan pengecualian
Kode dalam halaman penanganan pengecualian juga dapat melemparkan pengecualian. Halaman kesalahan produksi harus diuji secara menyeluruh dan berhati-hatilah untuk menghindari melempar pengecualian sendiri.
Tajuk respons
Setelah header untuk respons dikirim:
- Aplikasi tidak dapat mengubah kode status respons.
- Halaman pengecualian atau handler apa pun tidak dapat dijalankan. Respons harus diselesaikan atau koneksi dibatalkan.
Penanganan pengecualian server
Selain logika penanganan pengecualian dalam aplikasi, implementasi server HTTP dapat menangani beberapa pengecualian. Jika server menangkap pengecualian sebelum header respons dikirim, server mengirim 500 - Internal Server Error respons tanpa isi respons. Jika server menangkap pengecualian setelah header respons dikirim, server menutup koneksi. Permintaan yang tidak ditangani oleh aplikasi ditangani oleh server. Pengecualian apa pun yang terjadi ketika server menangani permintaan ditangani oleh penanganan pengecualian server. Halaman kesalahan kustom aplikasi, middleware penanganan pengecualian, dan filter tidak memengaruhi perilaku ini.
Penanganan pengecualian startup
Hanya lapisan hosting yang dapat menangani pengecualian yang terjadi selama startup aplikasi. Host dapat dikonfigurasi untuk menangkap kesalahan pada saat startup dan menangkap kesalahan yang terperinci.
Lapisan hosting dapat menampilkan halaman kesalahan untuk kesalahan startup yang terdeteksi hanya jika kesalahan terjadi setelah pengikatan alamat dan port host. Jika pengikatan gagal:
- Lapisan hosting mencatat pengecualian penting.
- Proses dotnet mengalami crash.
- Tidak ada halaman kesalahan yang ditampilkan ketika server HTTP adalah Kestrel.
Saat berjalan di IIS (atau Azure App Service) atau IIS Express, 502.5 - Kegagalan Proses dikembalikan oleh Modul ASP.NET Core jika proses tidak dapat dimulai. Untuk informasi selengkapnya, lihat Memecahkan masalah ASP.NET Core di Azure App Service dan IIS.
Halaman kesalahan database
Filter pengecualian halaman pengembang basis data AddDatabaseDeveloperPageExceptionFilter menangkap pengecualian terkait basis data yang dapat diselesaikan dengan migrasi Entity Framework Core. Ketika pengecualian ini terjadi, respons HTML dihasilkan dengan detail kemungkinan tindakan untuk menyelesaikan masalah. Halaman ini hanya diaktifkan di lingkungan Pengembangan. Kode berikut menambahkan filter pengecualian untuk halaman pengembang basis data:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Filter pengecualian
Di aplikasi MVC, filter pengecualian dapat dikonfigurasi secara global atau berdasarkan per pengontrol atau per tindakan. Di Razor aplikasi Pages, aplikasi tersebut dapat dikonfigurasi secara global atau per model halaman. Filter ini menangani pengecualian yang tidak tertangani yang terjadi selama eksekusi tindakan pengontrol atau filter lain. Untuk informasi selengkapnya, lihat Filter di ASP.NET Core.
Filter pengecualian berguna untuk menjebak pengecualian yang terjadi dalam tindakan MVC, tetapi tidak fleksibel seperti middleware penanganan pengecualian bawaan, UseExceptionHandler. Sebaiknya gunakan UseExceptionHandler, kecuali Anda perlu melakukan penanganan kesalahan secara berbeda berdasarkan tindakan MVC mana yang dipilih.
Kesalahan status model
Untuk informasi tentang cara menangani kesalahan status model, lihat Pengikatan model dan Validasi model.
Detail masalah
Rincian Masalah bukan satu-satunya format respons untuk menggambarkan kesalahan pada API HTTP, tetapi format ini biasanya digunakan untuk melaporkan kesalahan pada 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 header HTTP
Acceptpermintaan tidak menyertakantext/html.
Kode berikut mengonfigurasi aplikasi untuk menghasilkan respons detail masalah untuk semua respons kesalahan klien HTTP dan server yang belum memiliki konten isi:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Bagian berikutnya memperlihatkan cara menyesuaikan isi respons detail masalah.
Menyesuaikan detail masalah
Pembuatan ProblemDetails otomatis dapat dikustomisasi menggunakan salah satu opsi berikut:
- Menggunakan
ProblemDetailsOptions.CustomizeProblemDetails - Gunakan kustom
IProblemDetailsWriter -
IProblemDetailsServiceMemanggil di middleware
CustomizeProblemDetails operasi
Detail masalah yang dihasilkan dapat disesuaikan menggunakan CustomizeProblemDetails, dan kustomisasi diterapkan ke semua detail masalah yang dihasilkan secara otomatis.
Kode berikut menggunakan ProblemDetailsOptions untuk mengatur CustomizeProblemDetails:
builder.Services.AddProblemDetails(options =>
options.CustomizeProblemDetails = ctx =>
ctx.ProblemDetails.Extensions.Add("nodeId", Environment.MachineName));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Misalnya, HTTP Status 400 Bad Request hasil titik akhir menghasilkan isi respons detail masalah berikut:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Kustom IProblemDetailsWriter
Implementasi IProblemDetailsWriter dapat dibuat untuk kustomisasi tingkat lanjut.
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));
}
}
Catatan: Saat menggunakan kustom IProblemDetailsWriter, kustom IProblemDetailsWriter harus didaftarkan sebelum memanggil AddRazorPages, , AddControllers, AddControllersWithViewsatau AddMvc:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTransient<IProblemDetailsWriter, SampleProblemDetailsWriter>();
var app = builder.Build();
// 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<IProblemDetailsWriter>() is
{ } problemDetailsService)
{
if (problemDetailsService.CanWrite(new ProblemDetailsContext() { HttpContext = context }))
{
(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.Run();
Detail masalah dari Middleware
Pendekatan alternatif untuk menggunakan ProblemDetailsOptions dengan CustomizeProblemDetails adalah mengatur ProblemDetails di middleware. Respons detail masalah dapat ditulis dengan memanggil 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();
Dalam kode sebelumnya, endpoint API minimal /divide dan /squareroot mengembalikan respons masalah kustom yang diharapkan ketika ada input yang salah.
Titik akhir pengontrol API mengembalikan respons masalah default pada input kesalahan, bukan respons masalah kustom. Respons masalah default dikembalikan karena pengontrol API telah menulis ke aliran respons, Detail masalah untuk kode status error, sebelum IProblemDetailsService.WriteAsync dipanggil, sehingga respons tidak ditulis lagi.
Berikut ini ValuesController mengembalikan BadRequestResult, yang menulis ke aliran respons dan oleh karena itu mencegah respons masalah kustom dikembalikan.
[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));
}
}
Berikut ini Values3Controller mengembalikan ControllerBase.Problem sehingga hasil masalah kustom yang diharapkan dikembalikan:
[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));
}
}
Menghasilkan payload ProblemDetails untuk pengecualian
Pertimbangkan aplikasi berikut:
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();
Di lingkungan non-pengembangan, ketika pengecualian terjadi, berikut ini adalah respons ProblemDetails standar yang dikembalikan ke klien:
{
"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"
}
Untuk sebagian besar aplikasi, kode sebelumnya adalah semua yang diperlukan untuk pengecualian. Namun, bagian berikut menunjukkan cara mendapatkan respons masalah yang lebih rinci.
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan dan menulis respons detail masalah dengan 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 = "Argument exception";
detail = "Invalid input";
type = "https://errors.example.com/argumentException";
}
await problemDetailsService.WriteAsync(new ProblemDetailsContext
{
HttpContext = context,
ProblemDetails =
{
Title = title,
Detail = detail,
Type = type
}
});
}
});
});
}
app.MapControllers();
app.Run();
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Pendekatan alternatif untuk menghasilkan detail masalah adalah menggunakan paket NuGet pihak ketiga Hellang.Middleware.ProblemDetails yang dapat digunakan untuk memetakan pengecualian dan kesalahan klien ke detail masalah.
Sumber daya tambahan
Oleh Tom Dykstra
Artikel ini membahas pendekatan umum untuk menangani kesalahan di aplikasi web ASP.NET Core. Lihat juga Menangani kesalahan di API inti ASP.NET.
Halaman pengecualian pengembang perangkat lunak
Halaman Pengecualian Pengembang menampilkan informasi terperinci tentang pengecualian permintaan yang tidak tertangani. Aplikasi ASP.NET Core secara default mengaktifkan halaman pengecualian pengembang saat kedua kondisi berikut terpenuhi:
- Berjalan di lingkungan Pengembangan.
- Aplikasi yang dibuat dengan templat saat ini, yaitu, menggunakan WebApplication.CreateBuilder. Aplikasi yang dibuat menggunakan
WebHost.CreateDefaultBuilderharus mengaktifkan halaman pengecualian pengembang dengan memanggilapp.UseDeveloperExceptionPagediConfigure.
Halaman pengecualian pengembang berjalan lebih awal di pipeline middleware, sehingga dapat menangkap pengecualian yang tidak tertangani yang dilemparkan oleh middleware berikutnya.
Informasi pengecualian terperinci tidak boleh ditampilkan secara publik saat aplikasi berjalan di lingkungan 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
Halaman Pengecualian Pengembang tidak dijamin untuk memberikan informasi apa pun. Gunakan Pengelogan untuk informasi kesalahan lengkap.
Halaman penanganan pengecualian
Untuk mengonfigurasi halaman penanganan kesalahan kustom untuk lingkungan Produksi, panggil UseExceptionHandler. Middleware penanganan pengecualian ini:
- Menangkap dan mencatat pengecualian yang tidak tertangani.
- Menjalankan kembali permintaan dalam alur alternatif menggunakan jalur yang ditunjukkan. Permintaan tidak dijalankan kembali jika respons telah dimulai. Kode yang dihasilkan templat menjalankan kembali permintaan menggunakan
/Errorjalur .
Warning
Jika alur alternatif menghasilkan pengecualian miliknya, Exception Handling Middleware akan memunculkan kembali pengecualian asli.
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - UseExceptionHandler(IApplicationBuilder, String) Untuk kelebihan beban yang digunakan dalam templat, hanya jalur permintaan yang dimodifikasi, dan data rute dibersihkan. Data permintaan seperti header, metode, dan item semuanya digunakan kembali apa adanya.
- Layanan terlingkup tetap sama.
Dalam contoh berikut, UseExceptionHandler menambahkan middleware penanganan pengecualian di lingkungan selain Pengembangan.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Templat aplikasi Pages menyediakan halaman kesalahan (Razor) dan kelas (.cshtml) di PageModel. Untuk aplikasi MVC, templat proyek menyertakan Error metode tindakan dan tampilan Kesalahan untuk Home pengontrol.
Middleware penanganan pengecualian menjalankan kembali permintaan menggunakan metode HTTP asli . Jika sebuah endpoint handler kesalahan dibatasi hanya untuk sekumpulan metode HTTP tertentu, maka endpoint tersebut hanya akan berjalan untuk metode HTTP tersebut. Misalnya, tindakan pengontrol MVC yang menggunakan [HttpGet] atribut hanya berjalan untuk permintaan GET. Untuk memastikan bahwa semua permintaan mencapai halaman penanganan kesalahan kustom, jangan batasi ke sekumpulan metode HTTP tertentu.
Untuk menangani pengecualian secara berbeda berdasarkan metode HTTP asli:
- Untuk Razor Pages, buat beberapa metode handler. Misalnya, gunakan
OnGetuntuk menangani pengecualian GET dan gunakanOnPostuntuk menangani pengecualian POST. - Untuk MVC, terapkan atribut kata kerja HTTP ke beberapa tindakan. Misalnya, gunakan
[HttpGet]untuk menangani pengecualian GET dan gunakan[HttpPost]untuk menangani pengecualian POST.
Untuk mengizinkan pengguna yang tidak terautentikasi untuk melihat halaman penanganan kesalahan kustom, pastikan halaman tersebut mendukung akses anonim.
Mengakses pengecualian
Gunakan IExceptionHandlerPathFeature untuk mengakses pengecualian dan jalur permintaan asli dalam penangan kesalahan. Contoh berikut menggunakan IExceptionHandlerPathFeature untuk mendapatkan informasi selengkapnya tentang pengecualian yang dilemparkan:
[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.";
}
}
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Penangan pengecualian lambda
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan sebelum mengembalikan respons.
Kode berikut menggunakan lambda untuk penanganan pengecualian:
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();
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
IExceptionHandler
IExceptionHandler adalah antarmuka yang memberi pengembang panggilan balik untuk menangani pengecualian yang diketahui di lokasi yang terpusat.
implementasi IExceptionHandler didaftarkan dengan memanggil IServiceCollection.AddExceptionHandler<T> [IServiceCollection.AddExceptionHandler<T>]. Masa hidup instans IExceptionHandler adalah singleton. Beberapa implementasi dapat ditambahkan, dan dipanggil dalam urutan terdaftar.
Jika handler pengecualian menangani permintaan, handler dapat mengembalikan true untuk menghentikan pemrosesan. Jika pengecualian tidak ditangani oleh handler pengecualian apa pun, kontrol akan kembali ke perilaku dan opsi default dari middleware. Metrik dan log yang berbeda dipancarkan untuk pengecualian yang ditangani versus pengecualian yang tidak tertangani.
Contoh berikut menunjukkan implementasi IExceptionHandler:
using Microsoft.AspNetCore.Diagnostics;
namespace ErrorHandlingSample
{
public class CustomExceptionHandler : IExceptionHandler
{
private readonly ILogger<CustomExceptionHandler> logger;
public CustomExceptionHandler(ILogger<CustomExceptionHandler> logger)
{
this.logger = logger;
}
public ValueTask<bool> TryHandleAsync(
HttpContext httpContext,
Exception exception,
CancellationToken cancellationToken)
{
var exceptionMessage = exception.Message;
logger.LogError(
"Error Message: {exceptionMessage}, Time of occurrence {time}",
exceptionMessage, DateTime.UtcNow);
// Return false to continue with the default behavior
// - or - return true to signal that this exception is handled
return ValueTask.FromResult(false);
}
}
}
Contoh berikut menunjukkan cara mendaftarkan IExceptionHandler implementasi untuk injeksi dependensi:
using ErrorHandlingSample;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
builder.Services.AddExceptionHandler<CustomExceptionHandler>();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
// Remaining Program.cs code omitted for brevity
Saat kode sebelumnya berjalan di lingkungan Pengembangan:
- dipanggil
CustomExceptionHandlerterlebih dahulu untuk menangani pengecualian. - Setelah mencatat pengecualian,
TryHandleExceptionmetode mengembalikanfalse, sehingga halaman pengecualian pengembang ditampilkan.
Di lingkungan lain:
- dipanggil
CustomExceptionHandlerterlebih dahulu untuk menangani pengecualian. - Setelah mencatat pengecualian,
TryHandleExceptionmetode mengembalikanfalse, sehingga/Errorhalaman ditampilkan.
UseStatusCodePages
Secara default, aplikasi ASP.NET Core tidak menyediakan halaman kode status untuk kode status kesalahan HTTP, seperti 404 - Tidak Ditemukan. Saat aplikasi menetapkan kode status kesalahan HTTP 400-599 yang tidak memiliki isi, aplikasi mengembalikan kode status dan isi respons kosong. Untuk mengaktifkan handler teks saja sebagai default untuk kode status error umum, panggil UseStatusCodePages di Program.cs:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Panggil UseStatusCodePages sebelum meminta penanganan middleware. Misalnya, panggil UseStatusCodePages sebelum Static File Middleware dan Endpoints Middleware.
Saat UseStatusCodePages tidak digunakan, menavigasi ke URL tanpa titik akhir mengembalikan pesan kesalahan yang bergantung pada browser yang menunjukkan titik akhir tidak dapat ditemukan. Ketika UseStatusCodePages dipanggil, browser mengembalikan respons berikut:
Status Code: 404; Not Found
UseStatusCodePages biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak berguna bagi pengguna.
Note
Halaman kode status middleware tidak menangkap pengecualian. Untuk menyediakan halaman penanganan kesalahan khusus, gunakan halaman handler pengecualian.
GunakanStatusCodePages dengan string format
Untuk mengustomisasi tipe konten dan teks respons, gunakan versi overload dari UseStatusCodePages yang menerima tipe konten dan string format:
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}");
Dalam kode sebelumnya, {0} adalah tempat penampung untuk kode kesalahan.
UseStatusCodePages dengan string format biasanya tidak digunakan dalam produksi karena menampilkan pesan yang tidak berguna bagi pengguna.
Gunakan StatusCodePages dengan lambda
Untuk menentukan penanganan kesalahan kustom dan kode penulisan respons, gunakan kelebihan beban UseStatusCodePages yang mengambil ekspresi 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 dengan lambda biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak memberikan manfaat bagi pengguna.
UseStatusCodePagesWithRedirects
Metode ekstensi UseStatusCodePagesWithRedirects
- Mengirim kode status 302 - Ditemukan ke klien.
- Mengalihkan klien ke titik akhir penanganan kesalahan yang disediakan dalam templat URL. Titik akhir penanganan kesalahan biasanya menampilkan informasi kesalahan dan mengembalikan HTTP 200.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Templat URL dapat menyertakan {0} sebagai penampung untuk kode status, sesuai yang ditunjukkan dalam kode sebelumnya. Jika templat URL dimulai dengan ~ (tilde), ~ digantikan oleh PathBase milik aplikasi. Saat menentukan titik akhir di aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan saat aplikasi:
- Harus mengalihkan klien ke titik akhir yang berbeda, biasanya dalam kasus di mana aplikasi yang berbeda memproses kesalahan. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang dialihkan.
- Tidak seharusnya mempertahankan dan mengembalikan kode status asli saat memberikan respons pengalihan awal.
UseStatusCodePagesWithReExecute
Metode ekstensi UseStatusCodePagesWithReExecute
- Menghasilkan isi respons dengan mengeksekusi ulang alur permintaan menggunakan jalur alternatif.
- Tidak mengubah kode status, baik sebelum maupun sesudah menjalankan ulang alurnya.
Eksekusi alur baru dapat mengubah kode status respons, karena alur baru memiliki kontrol penuh atas kode status. Jika alur baru tidak mengubah kode status, kode status asli akan dikirim ke klien.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Jika titik akhir dalam aplikasi ditentukan, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan ketika aplikasi harus:
- Proses permintaan tanpa mengalihkan ke titik akhir yang berbeda. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang awalnya diminta.
- Pertahankan dan kembalikan kode status asli dengan respons.
Templat URL harus dimulai dengan / dan dapat menyertakan tempat penampung {0} untuk kode status. Untuk meneruskan kode status sebagai parameter string kueri, teruskan argumen kedua ke dalam UseStatusCodePagesWithReExecute. Contohnya:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
Titik akhir yang memproses kesalahan bisa mendapatkan URL asli yang menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
[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 = $"{statusCodeReExecuteFeature.OriginalPathBase}"
+ $"{statusCodeReExecuteFeature.OriginalPath}"
+ $"{statusCodeReExecuteFeature.OriginalQueryString}";
}
}
}
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - Layanan terlingkup tetap sama.
Menonaktifkan halaman kode status
Untuk menonaktifkan halaman kode status untuk pengontrol MVC atau metode tindakan, gunakan atribut [SkipStatusCodePages ].
Untuk menonaktifkan halaman kode status untuk permintaan tertentu dalam Razor metode handler Pages atau di pengontrol MVC, gunakan IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kode penanganan pengecualian
Kode dalam halaman penanganan pengecualian juga dapat melemparkan pengecualian. Halaman kesalahan produksi harus diuji secara menyeluruh dan berhati-hatilah untuk menghindari melempar pengecualian sendiri.
Tajuk respons
Setelah header untuk respons dikirim:
- Aplikasi tidak dapat mengubah kode status respons.
- Halaman pengecualian atau handler apa pun tidak dapat dijalankan. Respons harus diselesaikan atau koneksi dibatalkan.
Penanganan pengecualian server
Selain logika penanganan pengecualian dalam aplikasi, implementasi server HTTP dapat menangani beberapa pengecualian. Jika server menangkap pengecualian sebelum header respons dikirim, server mengirim 500 - Internal Server Error respons tanpa isi respons. Jika server menangkap pengecualian setelah header respons dikirim, server menutup koneksi. Permintaan yang tidak ditangani oleh aplikasi ditangani oleh server. Pengecualian apa pun yang terjadi ketika server menangani permintaan ditangani oleh penanganan pengecualian server. Halaman kesalahan kustom aplikasi, middleware penanganan pengecualian, dan filter tidak memengaruhi perilaku ini.
Penanganan pengecualian startup
Hanya lapisan hosting yang dapat menangani pengecualian yang terjadi selama startup aplikasi. Host dapat dikonfigurasi untuk menangkap kesalahan pada saat startup dan menangkap kesalahan yang terperinci.
Lapisan hosting dapat menampilkan halaman kesalahan untuk kesalahan startup yang terdeteksi hanya jika kesalahan terjadi setelah pengikatan alamat dan port host. Jika pengikatan gagal:
- Lapisan hosting mencatat pengecualian penting.
- Proses dotnet mengalami crash.
- Tidak ada halaman kesalahan yang ditampilkan ketika server HTTP adalah Kestrel.
Saat berjalan di IIS (atau Azure App Service) atau IIS Express, 502.5 - Kegagalan Proses dikembalikan oleh Modul ASP.NET Core jika proses tidak dapat dimulai. Untuk informasi selengkapnya, lihat Memecahkan masalah ASP.NET Core di Azure App Service dan IIS.
Halaman kesalahan database
Filter pengecualian halaman pengembang basis data AddDatabaseDeveloperPageExceptionFilter menangkap pengecualian terkait basis data yang dapat diselesaikan dengan migrasi Entity Framework Core. Ketika pengecualian ini terjadi, respons HTML dihasilkan dengan detail kemungkinan tindakan untuk menyelesaikan masalah. Halaman ini hanya diaktifkan di lingkungan Pengembangan. Kode berikut menambahkan filter pengecualian untuk halaman pengembang basis data:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Filter pengecualian
Di aplikasi MVC, filter pengecualian dapat dikonfigurasi secara global atau berdasarkan per pengontrol atau per tindakan. Di Razor aplikasi Pages, aplikasi tersebut dapat dikonfigurasi secara global atau per model halaman. Filter ini menangani pengecualian yang tidak tertangani yang terjadi selama eksekusi tindakan pengontrol atau filter lain. Untuk informasi selengkapnya, lihat Filter di ASP.NET Core.
Filter pengecualian berguna untuk menjebak pengecualian yang terjadi dalam tindakan MVC, tetapi tidak fleksibel seperti middleware penanganan pengecualian bawaan, UseExceptionHandler. Sebaiknya gunakan UseExceptionHandler, kecuali Anda perlu melakukan penanganan kesalahan secara berbeda berdasarkan tindakan MVC mana yang dipilih.
Kesalahan status model
Untuk informasi tentang cara menangani kesalahan status model, lihat Pengikatan model dan Validasi model.
Detail masalah
Rincian Masalah bukan satu-satunya format respons untuk menggambarkan kesalahan pada API HTTP, tetapi format ini biasanya digunakan untuk melaporkan kesalahan pada 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 header HTTP
Acceptpermintaan tidak menyertakantext/html.
Kode berikut mengonfigurasi aplikasi untuk menghasilkan respons detail masalah untuk semua respons kesalahan klien HTTP dan server yang belum memiliki konten isi:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Bagian berikutnya memperlihatkan cara menyesuaikan isi respons detail masalah.
Menyesuaikan detail masalah
Pembuatan ProblemDetails otomatis dapat dikustomisasi menggunakan salah satu opsi berikut:
- Menggunakan
ProblemDetailsOptions.CustomizeProblemDetails - Gunakan kustom
IProblemDetailsWriter -
IProblemDetailsServiceMemanggil di middleware
CustomizeProblemDetails operasi
Detail masalah yang dihasilkan dapat disesuaikan menggunakan CustomizeProblemDetails, dan kustomisasi diterapkan ke semua detail masalah yang dihasilkan secara otomatis.
Kode berikut menggunakan ProblemDetailsOptions untuk mengatur CustomizeProblemDetails:
builder.Services.AddProblemDetails(options =>
options.CustomizeProblemDetails = ctx =>
ctx.ProblemDetails.Extensions.Add("nodeId", Environment.MachineName));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Misalnya, HTTP Status 400 Bad Request hasil titik akhir menghasilkan isi respons detail masalah berikut:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Kustom IProblemDetailsWriter
Implementasi IProblemDetailsWriter dapat dibuat untuk kustomisasi tingkat lanjut.
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));
}
}
Catatan: Saat menggunakan kustom IProblemDetailsWriter, kustom IProblemDetailsWriter harus didaftarkan sebelum memanggil AddRazorPages, , AddControllers, AddControllersWithViewsatau AddMvc:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTransient<IProblemDetailsWriter, SampleProblemDetailsWriter>();
var app = builder.Build();
// 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<IProblemDetailsWriter>() is
{ } problemDetailsService)
{
if (problemDetailsService.CanWrite(new ProblemDetailsContext() { HttpContext = context }))
{
(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.Run();
Detail masalah dari Middleware
Pendekatan alternatif untuk menggunakan ProblemDetailsOptions dengan CustomizeProblemDetails adalah mengatur ProblemDetails di middleware. Respons detail masalah dapat ditulis dengan memanggil 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();
Dalam kode sebelumnya, endpoint API minimal /divide dan /squareroot mengembalikan respons masalah kustom yang diharapkan ketika ada input yang salah.
Titik akhir pengontrol API mengembalikan respons masalah default pada input kesalahan, bukan respons masalah kustom. Respons masalah default dikembalikan karena pengontrol API telah menulis ke aliran respons, Detail masalah untuk kode status error, sebelum IProblemDetailsService.WriteAsync dipanggil, sehingga respons tidak ditulis lagi.
Berikut ini ValuesController mengembalikan BadRequestResult, yang menulis ke aliran respons dan oleh karena itu mencegah respons masalah kustom dikembalikan.
[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));
}
}
Berikut ini Values3Controller mengembalikan ControllerBase.Problem sehingga hasil masalah kustom yang diharapkan dikembalikan:
[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));
}
}
Menghasilkan payload ProblemDetails untuk pengecualian
Pertimbangkan aplikasi berikut:
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();
Di lingkungan non-pengembangan, ketika pengecualian terjadi, berikut ini adalah respons ProblemDetails standar yang dikembalikan ke klien:
{
"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"
}
Untuk sebagian besar aplikasi, kode sebelumnya adalah semua yang diperlukan untuk pengecualian. Namun, bagian berikut menunjukkan cara mendapatkan respons masalah yang lebih rinci.
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan dan menulis respons detail masalah dengan 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 = "Argument exception";
detail = "Invalid input";
type = "https://errors.example.com/argumentException";
}
await problemDetailsService.WriteAsync(new ProblemDetailsContext
{
HttpContext = context,
ProblemDetails =
{
Title = title,
Detail = detail,
Type = type
}
});
}
});
});
}
app.MapControllers();
app.Run();
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Pendekatan alternatif untuk menghasilkan detail masalah adalah menggunakan paket NuGet pihak ketiga Hellang.Middleware.ProblemDetails yang dapat digunakan untuk memetakan pengecualian dan kesalahan klien ke detail masalah.
Sumber daya tambahan
Oleh Tom Dykstra
Artikel ini membahas pendekatan umum untuk menangani kesalahan di aplikasi web ASP.NET Core. Lihat juga Menangani kesalahan di API inti ASP.NET.
Halaman pengecualian pengembang perangkat lunak
Halaman Pengecualian Pengembang menampilkan informasi terperinci tentang pengecualian permintaan yang tidak tertangani. Aplikasi ASP.NET Core secara default mengaktifkan halaman pengecualian pengembang saat kedua kondisi berikut terpenuhi:
- Berjalan di lingkungan Pengembangan.
- Aplikasi yang dibuat dengan templat saat ini, yaitu, menggunakan WebApplication.CreateBuilder. Aplikasi yang dibuat menggunakan
WebHost.CreateDefaultBuilderharus mengaktifkan halaman pengecualian pengembang dengan memanggilapp.UseDeveloperExceptionPagediConfigure.
Halaman pengecualian pengembang berjalan lebih awal di pipeline middleware, sehingga dapat menangkap pengecualian yang tidak tertangani yang dilemparkan oleh middleware berikutnya.
Informasi pengecualian terperinci tidak boleh ditampilkan secara publik saat aplikasi berjalan di lingkungan 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
Halaman Pengecualian Pengembang tidak dijamin untuk memberikan informasi apa pun. Gunakan Pengelogan untuk informasi kesalahan lengkap.
Halaman penanganan pengecualian
Untuk mengonfigurasi halaman penanganan kesalahan kustom untuk lingkungan Produksi, panggil UseExceptionHandler. Middleware penanganan pengecualian ini:
- Menangkap dan mencatat pengecualian yang tidak tertangani.
- Menjalankan kembali permintaan dalam alur alternatif menggunakan jalur yang ditunjukkan. Permintaan tidak dijalankan kembali jika respons telah dimulai. Kode yang dihasilkan templat menjalankan kembali permintaan menggunakan
/Errorjalur .
Warning
Jika alur alternatif menghasilkan pengecualian miliknya, Exception Handling Middleware akan memunculkan kembali pengecualian asli.
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - UseExceptionHandler(IApplicationBuilder, String) Untuk kelebihan beban yang digunakan dalam templat, hanya jalur permintaan yang dimodifikasi, dan data rute dibersihkan. Data permintaan seperti header, metode, dan item semuanya digunakan kembali apa adanya.
- Layanan terlingkup tetap sama.
Dalam contoh berikut, UseExceptionHandler menambahkan middleware penanganan pengecualian di lingkungan selain Pengembangan.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Templat aplikasi Pages menyediakan halaman kesalahan (Razor) dan kelas (.cshtml) di PageModel. Untuk aplikasi MVC, templat proyek menyertakan Error metode tindakan dan tampilan Kesalahan untuk Home pengontrol.
Middleware penanganan pengecualian menjalankan kembali permintaan menggunakan metode HTTP asli . Jika sebuah endpoint handler kesalahan dibatasi hanya untuk sekumpulan metode HTTP tertentu, maka endpoint tersebut hanya akan berjalan untuk metode HTTP tersebut. Misalnya, tindakan pengontrol MVC yang menggunakan [HttpGet] atribut hanya berjalan untuk permintaan GET. Untuk memastikan bahwa semua permintaan mencapai halaman penanganan kesalahan kustom, jangan batasi ke sekumpulan metode HTTP tertentu.
Untuk menangani pengecualian secara berbeda berdasarkan metode HTTP asli:
- Untuk Razor Pages, buat beberapa metode handler. Misalnya, gunakan
OnGetuntuk menangani pengecualian GET dan gunakanOnPostuntuk menangani pengecualian POST. - Untuk MVC, terapkan atribut kata kerja HTTP ke beberapa tindakan. Misalnya, gunakan
[HttpGet]untuk menangani pengecualian GET dan gunakan[HttpPost]untuk menangani pengecualian POST.
Untuk mengizinkan pengguna yang tidak terautentikasi untuk melihat halaman penanganan kesalahan kustom, pastikan halaman tersebut mendukung akses anonim.
Mengakses pengecualian
Gunakan IExceptionHandlerPathFeature untuk mengakses pengecualian dan jalur permintaan asli dalam penangan kesalahan. Contoh berikut menggunakan IExceptionHandlerPathFeature untuk mendapatkan informasi selengkapnya tentang pengecualian yang dilemparkan:
[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.";
}
}
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Penangan pengecualian lambda
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan sebelum mengembalikan respons.
Kode berikut menggunakan lambda untuk penanganan pengecualian:
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();
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
UseStatusCodePages
Secara default, aplikasi ASP.NET Core tidak menyediakan halaman kode status untuk kode status kesalahan HTTP, seperti 404 - Tidak Ditemukan. Saat aplikasi menetapkan kode status kesalahan HTTP 400-599 yang tidak memiliki isi, aplikasi mengembalikan kode status dan isi respons kosong. Untuk mengaktifkan handler teks saja sebagai default untuk kode status error umum, panggil UseStatusCodePages di Program.cs:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Panggil UseStatusCodePages sebelum meminta penanganan middleware. Misalnya, panggil UseStatusCodePages sebelum Static File Middleware dan Endpoints Middleware.
Saat UseStatusCodePages tidak digunakan, menavigasi ke URL tanpa titik akhir mengembalikan pesan kesalahan yang bergantung pada browser yang menunjukkan titik akhir tidak dapat ditemukan. Ketika UseStatusCodePages dipanggil, browser mengembalikan respons berikut:
Status Code: 404; Not Found
UseStatusCodePages biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak berguna bagi pengguna.
Note
Halaman kode status middleware tidak menangkap pengecualian. Untuk menyediakan halaman penanganan kesalahan khusus, gunakan halaman handler pengecualian.
GunakanStatusCodePages dengan string format
Untuk mengustomisasi tipe konten dan teks respons, gunakan versi overload dari UseStatusCodePages yang menerima tipe konten dan string format:
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}");
Dalam kode sebelumnya, {0} adalah tempat penampung untuk kode kesalahan.
UseStatusCodePages dengan string format biasanya tidak digunakan dalam produksi karena menampilkan pesan yang tidak berguna bagi pengguna.
Gunakan StatusCodePages dengan lambda
Untuk menentukan penanganan kesalahan kustom dan kode penulisan respons, gunakan kelebihan beban UseStatusCodePages yang mengambil ekspresi 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 dengan lambda biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak memberikan manfaat bagi pengguna.
UseStatusCodePagesWithRedirects
Metode ekstensi UseStatusCodePagesWithRedirects
- Mengirim kode status 302 - Ditemukan ke klien.
- Mengalihkan klien ke titik akhir penanganan kesalahan yang disediakan dalam templat URL. Titik akhir penanganan kesalahan biasanya menampilkan informasi kesalahan dan mengembalikan HTTP 200.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Templat URL dapat menyertakan {0} sebagai penampung untuk kode status, sesuai yang ditunjukkan dalam kode sebelumnya. Jika templat URL dimulai dengan ~ (tilde), ~ digantikan oleh PathBase milik aplikasi. Saat menentukan titik akhir di aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan saat aplikasi:
- Harus mengalihkan klien ke titik akhir yang berbeda, biasanya dalam kasus di mana aplikasi yang berbeda memproses kesalahan. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang dialihkan.
- Tidak seharusnya mempertahankan dan mengembalikan kode status asli saat memberikan respons pengalihan awal.
UseStatusCodePagesWithReExecute
Metode ekstensi UseStatusCodePagesWithReExecute
- Menghasilkan isi respons dengan mengeksekusi ulang alur permintaan menggunakan jalur alternatif.
- Tidak mengubah kode status, baik sebelum maupun sesudah menjalankan ulang alurnya.
Eksekusi alur baru dapat mengubah kode status respons, karena alur baru memiliki kontrol penuh atas kode status. Jika alur baru tidak mengubah kode status, kode status asli akan dikirim ke klien.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Jika titik akhir dalam aplikasi ditentukan, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan ketika aplikasi harus:
- Proses permintaan tanpa mengalihkan ke titik akhir yang berbeda. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang awalnya diminta.
- Pertahankan dan kembalikan kode status asli dengan respons.
Templat URL harus dimulai dengan / dan dapat menyertakan tempat penampung {0} untuk kode status. Untuk meneruskan kode status sebagai parameter string kueri, teruskan argumen kedua ke dalam UseStatusCodePagesWithReExecute. Contohnya:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
Titik akhir yang memproses kesalahan bisa mendapatkan URL asli yang menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
[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 = $"{statusCodeReExecuteFeature.OriginalPathBase}"
+ $"{statusCodeReExecuteFeature.OriginalPath}"
+ $"{statusCodeReExecuteFeature.OriginalQueryString}";
}
}
}
Karena middleware ini dapat menjalankan kembali alur permintaan:
- Middleware perlu menangani reentrancy dengan permintaan yang sama. Ini biasanya berarti membersihkan status mereka setelah memanggil
_nextatau melakukan proses caching padaHttpContextuntuk menghindari pengulangan. Saat berhadapan dengan isi permintaan, ini berarti buffering atau penyimpanan sementara hasil seperti pembaca formulir. - Layanan terlingkup tetap sama.
Menonaktifkan halaman kode status
Untuk menonaktifkan halaman kode status untuk pengontrol MVC atau metode tindakan, gunakan atribut [SkipStatusCodePages ].
Untuk menonaktifkan halaman kode status untuk permintaan tertentu dalam Razor metode handler Pages atau di pengontrol MVC, gunakan IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kode penanganan pengecualian
Kode dalam halaman penanganan pengecualian juga dapat melemparkan pengecualian. Halaman kesalahan produksi harus diuji secara menyeluruh dan berhati-hatilah untuk menghindari melempar pengecualian sendiri.
Tajuk respons
Setelah header untuk respons dikirim:
- Aplikasi tidak dapat mengubah kode status respons.
- Halaman pengecualian atau handler apa pun tidak dapat dijalankan. Respons harus diselesaikan atau koneksi dibatalkan.
Penanganan pengecualian server
Selain logika penanganan pengecualian dalam aplikasi, implementasi server HTTP dapat menangani beberapa pengecualian. Jika server menangkap pengecualian sebelum header respons dikirim, server mengirim 500 - Internal Server Error respons tanpa isi respons. Jika server menangkap pengecualian setelah header respons dikirim, server menutup koneksi. Permintaan yang tidak ditangani oleh aplikasi ditangani oleh server. Pengecualian apa pun yang terjadi ketika server menangani permintaan ditangani oleh penanganan pengecualian server. Halaman kesalahan kustom aplikasi, middleware penanganan pengecualian, dan filter tidak memengaruhi perilaku ini.
Penanganan pengecualian startup
Hanya lapisan hosting yang dapat menangani pengecualian yang terjadi selama startup aplikasi. Host dapat dikonfigurasi untuk menangkap kesalahan pada saat startup dan menangkap kesalahan yang terperinci.
Lapisan hosting dapat menampilkan halaman kesalahan untuk kesalahan startup yang terdeteksi hanya jika kesalahan terjadi setelah pengikatan alamat dan port host. Jika pengikatan gagal:
- Lapisan hosting mencatat pengecualian penting.
- Proses dotnet mengalami crash.
- Tidak ada halaman kesalahan yang ditampilkan ketika server HTTP adalah Kestrel.
Saat berjalan di IIS (atau Azure App Service) atau IIS Express, 502.5 - Kegagalan Proses dikembalikan oleh Modul ASP.NET Core jika proses tidak dapat dimulai. Untuk informasi selengkapnya, lihat Memecahkan masalah ASP.NET Core di Azure App Service dan IIS.
Halaman kesalahan database
Filter pengecualian halaman pengembang basis data AddDatabaseDeveloperPageExceptionFilter menangkap pengecualian terkait basis data yang dapat diselesaikan dengan migrasi Entity Framework Core. Ketika pengecualian ini terjadi, respons HTML dihasilkan dengan detail kemungkinan tindakan untuk menyelesaikan masalah. Halaman ini hanya diaktifkan di lingkungan Pengembangan. Kode berikut menambahkan filter pengecualian untuk halaman pengembang basis data:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Filter pengecualian
Di aplikasi MVC, filter pengecualian dapat dikonfigurasi secara global atau berdasarkan per pengontrol atau per tindakan. Di Razor aplikasi Pages, aplikasi tersebut dapat dikonfigurasi secara global atau per model halaman. Filter ini menangani pengecualian yang tidak tertangani yang terjadi selama eksekusi tindakan pengontrol atau filter lain. Untuk informasi selengkapnya, lihat Filter di ASP.NET Core.
Filter pengecualian berguna untuk menjebak pengecualian yang terjadi dalam tindakan MVC, tetapi tidak fleksibel seperti middleware penanganan pengecualian bawaan, UseExceptionHandler. Sebaiknya gunakan UseExceptionHandler, kecuali Anda perlu melakukan penanganan kesalahan secara berbeda berdasarkan tindakan MVC mana yang dipilih.
Kesalahan status model
Untuk informasi tentang cara menangani kesalahan status model, lihat Pengikatan model dan Validasi model.
Detail masalah
Rincian Masalah bukan satu-satunya format respons untuk menggambarkan kesalahan pada API HTTP, tetapi format ini biasanya digunakan untuk melaporkan kesalahan pada 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 header HTTP
Acceptpermintaan tidak menyertakantext/html.
Kode berikut mengonfigurasi aplikasi untuk menghasilkan respons detail masalah untuk semua respons kesalahan klien HTTP dan server yang belum memiliki konten isi:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Bagian berikutnya memperlihatkan cara menyesuaikan isi respons detail masalah.
Menyesuaikan detail masalah
Pembuatan ProblemDetails otomatis dapat dikustomisasi menggunakan salah satu opsi berikut:
- Menggunakan
ProblemDetailsOptions.CustomizeProblemDetails - Gunakan kustom
IProblemDetailsWriter -
IProblemDetailsServiceMemanggil di middleware
CustomizeProblemDetails operasi
Detail masalah yang dihasilkan dapat disesuaikan menggunakan CustomizeProblemDetails, dan kustomisasi diterapkan ke semua detail masalah yang dihasilkan secara otomatis.
Kode berikut menggunakan ProblemDetailsOptions untuk mengatur CustomizeProblemDetails:
builder.Services.AddProblemDetails(options =>
options.CustomizeProblemDetails = ctx =>
ctx.ProblemDetails.Extensions.Add("nodeId", Environment.MachineName));
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
Misalnya, HTTP Status 400 Bad Request hasil titik akhir menghasilkan isi respons detail masalah berikut:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Kustom IProblemDetailsWriter
Implementasi IProblemDetailsWriter dapat dibuat untuk kustomisasi tingkat lanjut.
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));
}
}
Catatan: Saat menggunakan kustom IProblemDetailsWriter, kustom IProblemDetailsWriter harus didaftarkan sebelum memanggil AddRazorPages, , AddControllers, AddControllersWithViewsatau AddMvc:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTransient<IProblemDetailsWriter, SampleProblemDetailsWriter>();
var app = builder.Build();
// 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<IProblemDetailsWriter>() is
{ } problemDetailsService)
{
if (problemDetailsService.CanWrite(new ProblemDetailsContext() { HttpContext = context }))
{
(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.Run();
Detail masalah dari Middleware
Pendekatan alternatif untuk menggunakan ProblemDetailsOptions dengan CustomizeProblemDetails adalah mengatur ProblemDetails di middleware. Respons detail masalah dapat ditulis dengan memanggil 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();
Dalam kode sebelumnya, endpoint API minimal /divide dan /squareroot mengembalikan respons masalah kustom yang diharapkan ketika ada input yang salah.
Titik akhir pengontrol API mengembalikan respons masalah default pada input kesalahan, bukan respons masalah kustom. Respons masalah default dikembalikan karena pengontrol API telah menulis ke aliran respons, Detail masalah untuk kode status error, sebelum IProblemDetailsService.WriteAsync dipanggil, sehingga respons tidak ditulis lagi.
Berikut ini ValuesController mengembalikan BadRequestResult, yang menulis ke aliran respons dan oleh karena itu mencegah respons masalah kustom dikembalikan.
[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));
}
}
Berikut ini Values3Controller mengembalikan ControllerBase.Problem sehingga hasil masalah kustom yang diharapkan dikembalikan:
[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));
}
}
Menghasilkan payload ProblemDetails untuk pengecualian
Pertimbangkan aplikasi berikut:
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();
Di lingkungan non-pengembangan, ketika pengecualian terjadi, berikut ini adalah respons ProblemDetails standar yang dikembalikan ke klien:
{
"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"
}
Untuk sebagian besar aplikasi, kode sebelumnya adalah semua yang diperlukan untuk pengecualian. Namun, bagian berikut menunjukkan cara mendapatkan respons masalah yang lebih rinci.
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan dan menulis respons detail masalah dengan 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 = "Argument exception";
detail = "Invalid input";
type = "https://errors.example.com/argumentException";
}
await problemDetailsService.WriteAsync(new ProblemDetailsContext
{
HttpContext = context,
ProblemDetails =
{
Title = title,
Detail = detail,
Type = type
}
});
}
});
});
}
app.MapControllers();
app.Run();
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Pendekatan alternatif untuk menghasilkan detail masalah adalah menggunakan paket NuGet pihak ketiga Hellang.Middleware.ProblemDetails yang dapat digunakan untuk memetakan pengecualian dan kesalahan klien ke detail masalah.
Sumber daya tambahan
Oleh Tom Dykstra
Artikel ini membahas pendekatan umum untuk menangani kesalahan di aplikasi web ASP.NET Core. Lihat Menangani kesalahan di API inti ASP.NET untuk API web.
Halaman pengecualian pengembang perangkat lunak
Halaman Pengecualian Pengembang menampilkan informasi terperinci tentang pengecualian permintaan yang tidak tertangani. Aplikasi ASP.NET Core secara default mengaktifkan halaman pengecualian pengembang saat kedua kondisi berikut terpenuhi:
- Berjalan di lingkungan Pengembangan.
- Aplikasi yang dibuat dengan templat saat ini, yaitu, menggunakan WebApplication.CreateBuilder. Aplikasi yang dibuat menggunakan
WebHost.CreateDefaultBuilderharus mengaktifkan halaman pengecualian pengembang dengan memanggilapp.UseDeveloperExceptionPagediConfigure.
Halaman pengecualian pengembang berjalan lebih awal di pipeline middleware, sehingga dapat menangkap pengecualian yang tidak tertangani yang dilemparkan oleh middleware berikutnya.
Informasi pengecualian terperinci tidak boleh ditampilkan secara publik saat aplikasi berjalan di lingkungan 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
Halaman Pengecualian Pengembang tidak dijamin untuk memberikan informasi apa pun. Gunakan Pengelogan untuk informasi kesalahan lengkap.
Halaman penanganan pengecualian
Untuk mengonfigurasi halaman penanganan kesalahan kustom untuk lingkungan Produksi, panggil UseExceptionHandler. Middleware penanganan pengecualian ini:
- Menangkap dan mencatat pengecualian yang tidak tertangani.
- Menjalankan kembali permintaan dalam alur alternatif menggunakan jalur yang ditunjukkan. Permintaan tidak dijalankan kembali jika respons telah dimulai. Kode yang dihasilkan templat menjalankan kembali permintaan menggunakan
/Errorjalur .
Warning
Jika alur alternatif menghasilkan pengecualian miliknya, Exception Handling Middleware akan memunculkan kembali pengecualian asli.
Dalam contoh berikut, UseExceptionHandler menambahkan middleware penanganan pengecualian di lingkungan selain Pengembangan.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Templat aplikasi Pages menyediakan halaman kesalahan (Razor) dan kelas (.cshtml) di PageModel. Untuk aplikasi MVC, templat proyek menyertakan Error metode tindakan dan tampilan Kesalahan untuk Home pengontrol.
Middleware penanganan pengecualian menjalankan kembali permintaan menggunakan metode HTTP asli . Jika sebuah endpoint handler kesalahan dibatasi hanya untuk sekumpulan metode HTTP tertentu, maka endpoint tersebut hanya akan berjalan untuk metode HTTP tersebut. Misalnya, tindakan pengontrol MVC yang menggunakan [HttpGet] atribut hanya berjalan untuk permintaan GET. Untuk memastikan bahwa semua permintaan mencapai halaman penanganan kesalahan kustom, jangan batasi ke sekumpulan metode HTTP tertentu.
Untuk menangani pengecualian secara berbeda berdasarkan metode HTTP asli:
- Untuk Razor Pages, buat beberapa metode handler. Misalnya, gunakan
OnGetuntuk menangani pengecualian GET dan gunakanOnPostuntuk menangani pengecualian POST. - Untuk MVC, terapkan atribut kata kerja HTTP ke beberapa tindakan. Misalnya, gunakan
[HttpGet]untuk menangani pengecualian GET dan gunakan[HttpPost]untuk menangani pengecualian POST.
Untuk mengizinkan pengguna yang tidak terautentikasi untuk melihat halaman penanganan kesalahan kustom, pastikan halaman tersebut mendukung akses anonim.
Mengakses pengecualian
Gunakan IExceptionHandlerPathFeature untuk mengakses pengecualian dan jalur permintaan asli dalam penangan kesalahan. Contoh berikut menggunakan IExceptionHandlerPathFeature untuk mendapatkan informasi selengkapnya tentang pengecualian yang dilemparkan:
[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.";
}
}
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Penangan pengecualian lambda
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan sebelum mengembalikan respons.
Kode berikut menggunakan lambda untuk penanganan pengecualian:
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();
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
UseStatusCodePages
Secara default, aplikasi ASP.NET Core tidak menyediakan halaman kode status untuk kode status kesalahan HTTP, seperti 404 - Tidak Ditemukan. Saat aplikasi menetapkan kode status kesalahan HTTP 400-599 yang tidak memiliki isi, aplikasi mengembalikan kode status dan isi respons kosong. Untuk mengaktifkan handler teks saja sebagai default untuk kode status error umum, panggil UseStatusCodePages di Program.cs:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Panggil UseStatusCodePages sebelum meminta penanganan middleware. Misalnya, panggil UseStatusCodePages sebelum Static File Middleware dan Endpoints Middleware.
Saat UseStatusCodePages tidak digunakan, menavigasi ke URL tanpa titik akhir mengembalikan pesan kesalahan yang bergantung pada browser yang menunjukkan titik akhir tidak dapat ditemukan. Ketika UseStatusCodePages dipanggil, browser mengembalikan respons berikut:
Status Code: 404; Not Found
UseStatusCodePages biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak berguna bagi pengguna.
Note
Halaman kode status middleware tidak menangkap pengecualian. Untuk menyediakan halaman penanganan kesalahan khusus, gunakan halaman handler pengecualian.
GunakanStatusCodePages dengan string format
Untuk mengustomisasi tipe konten dan teks respons, gunakan versi overload dari UseStatusCodePages yang menerima tipe konten dan string format:
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}");
Dalam kode sebelumnya, {0} adalah tempat penampung untuk kode kesalahan.
UseStatusCodePages dengan string format biasanya tidak digunakan dalam produksi karena menampilkan pesan yang tidak berguna bagi pengguna.
Gunakan StatusCodePages dengan lambda
Untuk menentukan penanganan kesalahan kustom dan kode penulisan respons, gunakan kelebihan beban UseStatusCodePages yang mengambil ekspresi 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 dengan lambda biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak memberikan manfaat bagi pengguna.
UseStatusCodePagesWithRedirects
Metode ekstensi UseStatusCodePagesWithRedirects
- Mengirim kode status 302 - Ditemukan ke klien.
- Mengalihkan klien ke titik akhir penanganan kesalahan yang disediakan dalam templat URL. Titik akhir penanganan kesalahan biasanya menampilkan informasi kesalahan dan mengembalikan HTTP 200.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Templat URL dapat menyertakan {0} sebagai penampung untuk kode status, sesuai yang ditunjukkan dalam kode sebelumnya. Jika templat URL dimulai dengan ~ (tilde), ~ digantikan oleh PathBase milik aplikasi. Saat menentukan titik akhir di aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan saat aplikasi:
- Harus mengalihkan klien ke titik akhir yang berbeda, biasanya dalam kasus di mana aplikasi yang berbeda memproses kesalahan. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang dialihkan.
- Tidak seharusnya mempertahankan dan mengembalikan kode status asli saat memberikan respons pengalihan awal.
UseStatusCodePagesWithReExecute
Metode ekstensi UseStatusCodePagesWithReExecute
- Mengembalikan kode status asli ke klien.
- Menghasilkan isi respons dengan mengeksekusi ulang alur permintaan menggunakan jalur alternatif.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Jika titik akhir dalam aplikasi ditentukan, buat tampilan atau Razor halaman MVC untuk titik akhir.
Metode ini umumnya digunakan ketika aplikasi harus:
- Proses permintaan tanpa mengalihkan ke titik akhir yang berbeda. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang awalnya diminta.
- Pertahankan dan kembalikan kode status asli dengan respons.
Templat URL harus dimulai dengan / dan dapat menyertakan tempat penampung {0} untuk kode status. Untuk meneruskan kode status sebagai parameter string kueri, teruskan argumen kedua ke dalam UseStatusCodePagesWithReExecute. Contohnya:
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
Titik akhir yang memproses kesalahan bisa mendapatkan URL asli yang menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
[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);
}
}
}
Menonaktifkan halaman kode status
Untuk menonaktifkan halaman kode status untuk pengontrol MVC atau metode tindakan, gunakan atribut [SkipStatusCodePages ].
Untuk menonaktifkan halaman kode status untuk permintaan tertentu dalam Razor metode handler Pages atau di pengontrol MVC, gunakan IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kode penanganan pengecualian
Kode dalam halaman penanganan pengecualian juga dapat melemparkan pengecualian. Halaman kesalahan produksi harus diuji secara menyeluruh dan berhati-hatilah untuk menghindari melempar pengecualian sendiri.
Tajuk respons
Setelah header untuk respons dikirim:
- Aplikasi tidak dapat mengubah kode status respons.
- Halaman pengecualian atau handler apa pun tidak dapat dijalankan. Respons harus diselesaikan atau koneksi dibatalkan.
Penanganan pengecualian server
Selain logika penanganan pengecualian dalam aplikasi, implementasi server HTTP dapat menangani beberapa pengecualian. Jika server menangkap pengecualian sebelum header respons dikirim, server mengirim 500 - Internal Server Error respons tanpa isi respons. Jika server menangkap pengecualian setelah header respons dikirim, server menutup koneksi. Permintaan yang tidak ditangani oleh aplikasi ditangani oleh server. Pengecualian apa pun yang terjadi ketika server menangani permintaan ditangani oleh penanganan pengecualian server. Halaman kesalahan kustom aplikasi, middleware penanganan pengecualian, dan filter tidak memengaruhi perilaku ini.
Penanganan pengecualian startup
Hanya lapisan hosting yang dapat menangani pengecualian yang terjadi selama startup aplikasi. Host dapat dikonfigurasi untuk menangkap kesalahan pada saat startup dan menangkap kesalahan yang terperinci.
Lapisan hosting dapat menampilkan halaman kesalahan untuk kesalahan startup yang terdeteksi hanya jika kesalahan terjadi setelah pengikatan alamat dan port host. Jika pengikatan gagal:
- Lapisan hosting mencatat pengecualian penting.
- Proses dotnet mengalami crash.
- Tidak ada halaman kesalahan yang ditampilkan ketika server HTTP adalah Kestrel.
Saat berjalan di IIS (atau Azure App Service) atau IIS Express, 502.5 - Kegagalan Proses dikembalikan oleh Modul ASP.NET Core jika proses tidak dapat dimulai. Untuk informasi selengkapnya, lihat Memecahkan masalah ASP.NET Core di Azure App Service dan IIS.
Halaman kesalahan database
Filter pengecualian halaman pengembang basis data AddDatabaseDeveloperPageExceptionFilter menangkap pengecualian terkait basis data yang dapat diselesaikan dengan migrasi Entity Framework Core. Ketika pengecualian ini terjadi, respons HTML dihasilkan dengan detail kemungkinan tindakan untuk menyelesaikan masalah. Halaman ini hanya diaktifkan di lingkungan Pengembangan. Kode berikut menambahkan filter pengecualian untuk halaman pengembang basis data:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Filter pengecualian
Di aplikasi MVC, filter pengecualian dapat dikonfigurasi secara global atau berdasarkan per pengontrol atau per tindakan. Di Razor aplikasi Pages, aplikasi tersebut dapat dikonfigurasi secara global atau per model halaman. Filter ini menangani pengecualian yang tidak tertangani yang terjadi selama eksekusi tindakan pengontrol atau filter lain. Untuk informasi selengkapnya, lihat Filter di ASP.NET Core.
Filter pengecualian berguna untuk menjebak pengecualian yang terjadi dalam tindakan MVC, tetapi tidak fleksibel seperti middleware penanganan pengecualian bawaan, UseExceptionHandler. Sebaiknya gunakan UseExceptionHandler, kecuali Anda perlu melakukan penanganan kesalahan secara berbeda berdasarkan tindakan MVC mana yang dipilih.
Kesalahan status model
Untuk informasi tentang cara menangani kesalahan status model, lihat Pengikatan model dan Validasi model.
Sumber daya tambahan
Oleh Kirk Larkin, Tom Dykstra, dan Steve Smith
Artikel ini membahas pendekatan umum untuk menangani kesalahan di aplikasi web ASP.NET Core. Lihat Menangani kesalahan di API inti ASP.NET untuk API web.
Melihat atau mengunduh kode sampel. (Cara mengunduh.) Tab jaringan pada alat pengembang browser F12 berguna saat menguji aplikasi sampel.
Halaman Pengecualian Pengembang
Halaman Pengecualian Pengembang menampilkan informasi terperinci tentang pengecualian permintaan yang tidak tertangani. Templat ASP.NET Core menghasilkan kode berikut:
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();
});
}
Kode yang disorot sebelumnya memungkinkan halaman pengecualian pengembang ditampilkan saat aplikasi berjalan di Lingkungan Pengembangan.
Template menempatkan UseDeveloperExceptionPage di awal pipeline middleware sehingga dapat menangkap pengecualian yang tidak tertangani yang dilemparkan dalam middleware berikutnya.
Kode sebelumnya memungkinkan Halaman Pengecualian Pengembang hanya ketika aplikasi berjalan di lingkungan Pengembangan. Informasi pengecualian terperinci tidak boleh ditampilkan secara publik saat aplikasi berjalan di lingkungan 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 kueri string, jika ada
- Cookie jika ada
- Headers
Halaman Pengecualian Pengembang tidak dijamin untuk memberikan informasi apa pun. Gunakan Pengelogan untuk informasi kesalahan lengkap.
Halaman penanganan pengecualian
Untuk mengonfigurasi halaman penanganan kesalahan kustom untuk lingkungan Produksi, panggil UseExceptionHandler. Middleware penanganan pengecualian ini:
- Menangkap dan mencatat pengecualian yang tidak tertangani.
- Menjalankan kembali permintaan dalam alur alternatif menggunakan jalur yang ditunjukkan. Permintaan tidak dijalankan kembali jika respons telah dimulai. Kode yang dihasilkan templat menjalankan kembali permintaan menggunakan
/Errorjalur .
Warning
Jika alur alternatif menghasilkan pengecualian miliknya, Exception Handling Middleware akan memunculkan kembali pengecualian asli.
Dalam contoh berikut, UseExceptionHandler menambahkan middleware penanganan pengecualian di lingkungan selain Pengembangan.
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Templat aplikasi Pages menyediakan halaman kesalahan (Razor) dan kelas (.cshtml) di PageModel. Untuk aplikasi MVC, templat proyek menyertakan Error metode tindakan dan tampilan Kesalahan untuk Home pengontrol.
Middleware penanganan pengecualian menjalankan kembali permintaan menggunakan metode HTTP asli . Jika sebuah endpoint handler kesalahan dibatasi hanya untuk sekumpulan metode HTTP tertentu, maka endpoint tersebut hanya akan berjalan untuk metode HTTP tersebut. Misalnya, tindakan pengontrol MVC yang menggunakan [HttpGet] atribut hanya berjalan untuk permintaan GET. Untuk memastikan bahwa semua permintaan mencapai halaman penanganan kesalahan kustom, jangan batasi ke sekumpulan metode HTTP tertentu.
Untuk menangani pengecualian secara berbeda berdasarkan metode HTTP asli:
- Untuk Razor Pages, buat beberapa metode handler. Misalnya, gunakan
OnGetuntuk menangani pengecualian GET dan gunakanOnPostuntuk menangani pengecualian POST. - Untuk MVC, terapkan atribut kata kerja HTTP ke beberapa tindakan. Misalnya, gunakan
[HttpGet]untuk menangani pengecualian GET dan gunakan[HttpPost]untuk menangani pengecualian POST.
Untuk mengizinkan pengguna yang tidak terautentikasi untuk melihat halaman penanganan kesalahan kustom, pastikan halaman tersebut mendukung akses anonim.
Mengakses pengecualian
Gunakan IExceptionHandlerPathFeature untuk mengakses pengecualian dan jalur permintaan asli dalam penangan kesalahan. Kode berikut menambahkan ExceptionMessage ke default Pages/Error.cshtml.cs yang dihasilkan oleh templat ASP.NET Core:
[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";
}
}
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Untuk menguji pengecualian di aplikasi sampel:
- Atur lingkungan ke produksi.
- Hapus komentar dari
webBuilder.UseStartup<Startup>();dalamProgram.cs. - Pilih Menghasilkan pengecualian di beranda.
Penangan pengecualian lambda
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan sebelum mengembalikan respons.
Kode berikut menggunakan lambda untuk penanganan pengecualian:
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();
});
}
Warning
Jangan memberikan informasi kesalahan sensitif dari IExceptionHandlerFeature atau IExceptionHandlerPathFeature ke klien. Melayani kesalahan adalah risiko keamanan.
Untuk menguji penanganan pengecualian lambda di aplikasi sampel:
- Atur lingkungan ke produksi.
- Hapus komentar dari
webBuilder.UseStartup<StartupLambda>();dalamProgram.cs. - Pilih Menghasilkan pengecualian di beranda.
UseStatusCodePages
Secara default, aplikasi ASP.NET Core tidak menyediakan halaman kode status untuk kode status kesalahan HTTP, seperti 404 - Tidak Ditemukan. Saat aplikasi menetapkan kode status kesalahan HTTP 400-599 yang tidak memiliki isi, aplikasi mengembalikan kode status dan isi respons kosong. Untuk menyediakan halaman kode status, gunakan middleware halaman kode status. Untuk mengaktifkan penangan default untuk teks saja pada kode status kesalahan umum, panggil UseStatusCodePages dalam metode Startup.Configure.
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();
});
}
Panggil UseStatusCodePages sebelum meminta penanganan middleware. Misalnya, panggil UseStatusCodePages sebelum Static File Middleware dan Endpoints Middleware.
Saat UseStatusCodePages tidak digunakan, menavigasi ke URL tanpa titik akhir mengembalikan pesan kesalahan yang bergantung pada browser yang menunjukkan titik akhir tidak dapat ditemukan. Misalnya, menavigasi ke Home/Privacy2. Ketika UseStatusCodePages dipanggil, browser mengembalikan:
Status Code: 404; Not Found
UseStatusCodePages biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak berguna bagi pengguna.
Untuk menguji UseStatusCodePages di aplikasi sampel:
- Atur lingkungan ke produksi.
- Hapus komentar dari
webBuilder.UseStartup<StartupUseStatusCodePages>();dalamProgram.cs. - Pilih tautan di halaman beranda.
Note
Halaman kode status middleware tidak menangkap pengecualian. Untuk menyediakan halaman penanganan kesalahan khusus, gunakan halaman handler pengecualian.
GunakanStatusCodePages dengan string format
Untuk mengustomisasi tipe konten dan teks respons, gunakan versi overload dari UseStatusCodePages yang menerima tipe konten dan string format:
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();
});
}
Dalam kode sebelumnya, {0} adalah tempat penampung untuk kode kesalahan.
UseStatusCodePages dengan string format biasanya tidak digunakan dalam produksi karena menampilkan pesan yang tidak berguna bagi pengguna.
Untuk menguji UseStatusCodePages di aplikasi sampel, hapus komentar dari webBuilder.UseStartup<StartupFormat>(); dalam Program.cs.
Gunakan StatusCodePages dengan lambda
Untuk menentukan penanganan kesalahan kustom dan kode penulisan respons, gunakan kelebihan beban UseStatusCodePages yang mengambil ekspresi 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 dengan lambda biasanya tidak digunakan dalam produksi karena mengembalikan pesan yang tidak memberikan manfaat bagi pengguna.
Untuk menguji UseStatusCodePages di aplikasi sampel, hapus komentar dari webBuilder.UseStartup<StartupStatusLambda>(); dalam Program.cs.
UseStatusCodePagesWithRedirects
Metode ekstensi UseStatusCodePagesWithRedirects
- Mengirim kode status 302 - Ditemukan ke klien.
- Mengalihkan klien ke titik akhir penanganan kesalahan yang disediakan dalam templat URL. Titik akhir penanganan kesalahan biasanya menampilkan informasi kesalahan dan mengembalikan HTTP 200.
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();
});
}
Templat URL dapat menyertakan {0} sebagai penampung untuk kode status, sesuai yang ditunjukkan dalam kode sebelumnya. Jika templat URL dimulai dengan ~ (tilde), ~ digantikan oleh PathBase milik aplikasi. Saat menentukan titik akhir di aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir.
Razor Untuk contoh Halaman, lihat Pages/MyStatusCode.cshtml di aplikasi sampel.
Metode ini umumnya digunakan saat aplikasi:
- Harus mengalihkan klien ke titik akhir yang berbeda, biasanya dalam kasus di mana aplikasi yang berbeda memproses kesalahan. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang dialihkan.
- Tidak seharusnya mempertahankan dan mengembalikan kode status asli saat memberikan respons pengalihan awal.
Untuk menguji UseStatusCodePages di aplikasi sampel, hapus komentar dari webBuilder.UseStartup<StartupSCredirect>(); dalam Program.cs.
UseStatusCodePagesWithReExecute
Metode ekstensi UseStatusCodePagesWithReExecute
- Mengembalikan kode status asli ke klien.
- Menghasilkan isi respons dengan mengeksekusi ulang alur permintaan menggunakan jalur alternatif.
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();
});
}
Jika titik akhir dalam aplikasi ditentukan, buat tampilan atau Razor halaman MVC untuk titik akhir. Pastikan UseStatusCodePagesWithReExecute ditempatkan sebelumnya UseRouting sehingga permintaan dapat dialihkan ke halaman status.
Razor Untuk contoh Halaman, lihat Pages/MyStatusCode2.cshtml di aplikasi sampel.
Metode ini umumnya digunakan ketika aplikasi harus:
- Proses permintaan tanpa mengalihkan ke titik akhir yang berbeda. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang awalnya diminta.
- Pertahankan dan kembalikan kode status asli dengan respons.
Templat URL dan string kueri dapat menyertakan sebuah tempat penampung {0} untuk kode status. Templat URL harus dimulai dengan /.
Titik akhir yang memproses kesalahan bisa mendapatkan URL asli yang menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
[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 Untuk contoh Halaman, lihat Pages/MyStatusCode2.cshtml di aplikasi sampel.
Untuk menguji UseStatusCodePages di aplikasi sampel, hapus komentar dari webBuilder.UseStartup<StartupSCreX>(); dalam Program.cs.
Menonaktifkan halaman kode status
Untuk menonaktifkan halaman kode status untuk pengontrol MVC atau metode tindakan, gunakan atribut [SkipStatusCodePages ].
Untuk menonaktifkan halaman kode status untuk permintaan tertentu dalam Razor metode handler Pages atau di pengontrol MVC, gunakan IStatusCodePagesFeature:
public void OnGet()
{
// using Microsoft.AspNetCore.Diagnostics;
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kode penanganan pengecualian
Kode dalam halaman penanganan pengecualian juga dapat melemparkan pengecualian. Halaman kesalahan produksi harus diuji secara menyeluruh dan berhati-hatilah untuk menghindari melempar pengecualian sendiri.
Tajuk respons
Setelah header untuk respons dikirim:
- Aplikasi tidak dapat mengubah kode status respons.
- Halaman pengecualian atau handler apa pun tidak dapat dijalankan. Respons harus diselesaikan atau koneksi dibatalkan.
Penanganan pengecualian server
Selain logika penanganan pengecualian dalam aplikasi, implementasi server HTTP dapat menangani beberapa pengecualian. Jika server menangkap pengecualian sebelum header respons dikirim, server mengirim 500 - Internal Server Error respons tanpa isi respons. Jika server menangkap pengecualian setelah header respons dikirim, server menutup koneksi. Permintaan yang tidak ditangani oleh aplikasi ditangani oleh server. Pengecualian apa pun yang terjadi ketika server menangani permintaan ditangani oleh penanganan pengecualian server. Halaman kesalahan kustom aplikasi, middleware penanganan pengecualian, dan filter tidak memengaruhi perilaku ini.
Penanganan pengecualian startup
Hanya lapisan hosting yang dapat menangani pengecualian yang terjadi selama startup aplikasi. Host dapat dikonfigurasi untuk menangkap kesalahan pada saat startup dan menangkap kesalahan yang terperinci.
Lapisan hosting dapat menampilkan halaman kesalahan untuk kesalahan startup yang terdeteksi hanya jika kesalahan terjadi setelah pengikatan alamat dan port host. Jika pengikatan gagal:
- Lapisan hosting mencatat pengecualian penting.
- Proses dotnet mengalami crash.
- Tidak ada halaman kesalahan yang ditampilkan ketika server HTTP adalah Kestrel.
Saat berjalan di IIS (atau Azure App Service) atau IIS Express, 502.5 - Kegagalan Proses dikembalikan oleh Modul ASP.NET Core jika proses tidak dapat dimulai. Untuk informasi selengkapnya, lihat Memecahkan masalah ASP.NET Core di Azure App Service dan IIS.
Halaman kesalahan database
Filter pengecualian halaman pengembang basis data AddDatabaseDeveloperPageExceptionFilter menangkap pengecualian terkait basis data yang dapat diselesaikan dengan migrasi Entity Framework Core. Ketika pengecualian ini terjadi, respons HTML dihasilkan dengan detail kemungkinan tindakan untuk menyelesaikan masalah. Halaman ini hanya diaktifkan di lingkungan Pengembangan. Kode berikut dihasilkan oleh templat ASP.NET Core Razor Pages saat akun pengguna individual ditentukan:
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();
}
Filter pengecualian
Di aplikasi MVC, filter pengecualian dapat dikonfigurasi secara global atau berdasarkan per pengontrol atau per tindakan. Di Razor aplikasi Pages, aplikasi tersebut dapat dikonfigurasi secara global atau per model halaman. Filter ini menangani pengecualian yang tidak tertangani yang terjadi selama eksekusi tindakan pengontrol atau filter lain. Untuk informasi selengkapnya, lihat Filter di ASP.NET Core.
Filter pengecualian berguna untuk menjebak pengecualian yang terjadi dalam tindakan MVC, tetapi tidak fleksibel seperti middleware penanganan pengecualian bawaan, UseExceptionHandler. Sebaiknya gunakan UseExceptionHandler, kecuali Anda perlu melakukan penanganan kesalahan secara berbeda berdasarkan tindakan MVC mana yang dipilih.
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();
});
}
Kesalahan status model
Untuk informasi tentang cara menangani kesalahan status model, lihat Pengikatan model dan Validasi model.
Sumber daya tambahan
Oleh Tom Dykstra, dan Steve Smith
Artikel ini membahas pendekatan umum untuk menangani kesalahan di aplikasi web ASP.NET Core. Lihat Menangani kesalahan di API inti ASP.NET untuk API web.
Melihat atau mengunduh kode sampel. (Cara mengunduh.)
Halaman Pengecualian Pengembang
Halaman Ekssepsi Pengembang menampilkan informasi terperinci tentang ekssepsi permintaan. Templat ASP.NET Core menghasilkan kode berikut:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Kode sebelumnya mengaktifkan halaman pengecualian pengembang ketika aplikasi berjalan di lingkungan Pengembangan.
Tempatkan templat UseDeveloperExceptionPage sebelum middleware mana pun sehingga pengecualian tersangkut dalam middleware yang mengikutinya.
Kode sebelumnya memungkinkan Halaman Pengecualian Pengembang hanya ketika aplikasi berjalan di lingkungan Pengembangan. Informasi pengecualian terperinci tidak boleh ditampilkan secara publik saat aplikasi berjalan dalam produksi. Untuk informasi selengkapnya tentang mengonfigurasi lingkungan, lihat lingkungan runtime ASP.NET Core.
Halaman Pengecualian Pengembang menyertakan informasi berikut tentang pengecualian dan permintaan:
- Pelacakan tumpukan
- Parameter kueri string, jika ada
- Cookie jika ada
- Headers
Halaman penanganan pengecualian
Untuk mengonfigurasi halaman penanganan kesalahan kustom untuk lingkungan Produksi, gunakan Middleware Penanganan Pengecualian. Middleware:
- Menangkap dan mencatat pengecualian.
- Menjalankan kembali permintaan dalam alur alternatif untuk halaman atau pengontrol yang ditunjukkan. Permintaan tidak dijalankan kembali jika respons telah dimulai. Kode yang dihasilkan templat menjalankan kembali permintaan ke
/Error.
Dalam contoh berikut, UseExceptionHandler menambahkan perangkat lunak perantara untuk penanganan pengecualian di lingkungan non-pengembangan.
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Templat aplikasi Pages menyediakan halaman kesalahan (Razor) dan kelas (.cshtml) di PageModel. Untuk aplikasi MVC, templat proyek menyertakan metode aksi Error dan tampilan Error di Home pengontrol.
Jangan tandai metode tindakan penangan kesalahan dengan atribut metode HTTP, seperti HttpGet. Kata kerja eksplisit mencegah beberapa permintaan mencapai metode . Izinkan akses anonim ke metode jika pengguna yang tidak diaturentikasi akan melihat tampilan kesalahan.
Mengakses pengecualian
Gunakan IExceptionHandlerPathFeature untuk mengakses pengecualian dan jalur permintaan asli di pengontrol atau halaman penangan kesalahan:
[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";
}
}
}
Warning
Jangan melayani informasi kesalahan sensitif kepada klien. Melayani kesalahan adalah risiko keamanan.
Untuk memicu halaman penanganan pengecualian sebelumnya, atur lingkungan ke lingkungan produksi dan buat pengecualian.
Penangan pengecualian lambda
Alternatif untuk halaman penangan pengecualian khusus adalah menyediakan lambda ke UseExceptionHandler. Menggunakan lambda memungkinkan akses ke kesalahan sebelum mengembalikan respons.
Berikut adalah contoh penggunaan lambda untuk penanganan pengecualian:
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();
}
Dalam kode sebelumnya, await context.Response.WriteAsync(new string(' ', 512)); ditambahkan sehingga browser Internet Explorer menampilkan pesan kesalahan daripada pesan kesalahan IE. Untuk informasi lebih lanjut, lihat masalah GitHub ini.
Warning
Jangan memberikan informasi kesalahan sensitif dari IExceptionHandlerFeature atau IExceptionHandlerPathFeature ke klien. Melayani kesalahan adalah risiko keamanan.
Untuk melihat hasil penanganan pengecualian lambda di aplikasi sampel , gunakan petunjuk praprosepsi ProdEnvironment dan ErrorHandlerLambda, dan pilih Picu pengecualian di halaman beranda.
UseStatusCodePages
Secara default, aplikasi ASP.NET Core tidak menyediakan halaman kode status untuk kode status HTTP, seperti 404 - Tidak Ditemukan. Aplikasi mengembalikan kode status dan isi respons kosong. Untuk menyediakan halaman kode status, gunakan middleware Halaman Kode Status.
Middleware tersedia oleh paket Microsoft.AspNetCore.Diagnostics .
Untuk mengaktifkan penangan default untuk teks saja pada kode status kesalahan umum, panggil UseStatusCodePages dalam metode Startup.Configure.
app.UseStatusCodePages();
Panggil UseStatusCodePages sebelum meminta penanganan middleware (misalnya, Middleware File Statis dan Middleware MVC).
Saat UseStatusCodePages tidak digunakan, menavigasi ke URL tanpa titik akhir mengembalikan pesan kesalahan dependen browser yang menunjukkan titik akhir tidak dapat ditemukan. Misalnya, menavigasi ke Home/Privacy2. Ketika UseStatusCodePages dipanggil, browser mengembalikan:
Status Code: 404; Not Found
GunakanStatusCodePages dengan string format
Untuk mengustomisasi tipe konten dan teks respons, gunakan versi overload dari UseStatusCodePages yang menerima tipe konten dan string format:
app.UseStatusCodePages(
"text/plain", "Status code page, status code: {0}");
Gunakan StatusCodePages dengan lambda
Untuk menentukan penanganan kesalahan kustom dan kode penulisan respons, gunakan kelebihan beban UseStatusCodePages yang mengambil ekspresi 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
Metode ekstensi UseStatusCodePagesWithRedirects
- Mengirim kode status 302 - Ditemukan ke klien.
- Mengalihkan klien ke lokasi yang disediakan dalam templat URL.
app.UseStatusCodePagesWithRedirects("/StatusCode?code={0}");
Templat URL dapat menyertakan {0} sebagai penampung kode status HTTP, seperti yang ditunjukkan dalam contoh. Jika templat URL dimulai dengan ~ (tilde), ~ digantikan oleh PathBase milik aplikasi. Jika Anda mengarahkan ke titik akhir dalam aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir.
Razor Untuk contoh Halaman, lihat Pages/StatusCode.cshtml di aplikasi sampel.
Metode ini umumnya digunakan saat aplikasi:
- Harus mengalihkan klien ke titik akhir yang berbeda, biasanya dalam kasus di mana aplikasi yang berbeda memproses kesalahan. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang dialihkan.
- Tidak seharusnya mempertahankan dan mengembalikan kode status asli saat memberikan respons pengalihan awal.
UseStatusCodePagesWithReExecute
Metode ekstensi UseStatusCodePagesWithReExecute
- Mengembalikan kode status asli ke klien.
- Menghasilkan isi respons dengan mengeksekusi ulang alur permintaan menggunakan jalur alternatif.
app.UseStatusCodePagesWithReExecute("/StatusCode","?code={0}");
Jika Anda mengarahkan ke titik akhir dalam aplikasi, buat tampilan atau Razor halaman MVC untuk titik akhir. Pastikan UseStatusCodePagesWithReExecute ditempatkan sebelumnya UseRouting sehingga permintaan dapat dialihkan ke halaman status.
Razor Untuk contoh Halaman, lihat Pages/StatusCode.cshtml di aplikasi sampel.
Metode ini umumnya digunakan ketika aplikasi harus:
- Proses permintaan tanpa mengalihkan ke titik akhir yang berbeda. Untuk aplikasi web, bilah alamat browser klien mencerminkan titik akhir yang awalnya diminta.
- Pertahankan dan kembalikan kode status asli dengan respons.
URL dan templat string kueri dapat menyertakan tempat penampung ({0}) untuk kode status. Templat URL harus dimulai dengan garis miring (/). Saat menggunakan placeholder di jalur, pastikan bahwa titik akhir (halaman atau pengontrol) bisa memproses segmen jalur. Misalnya, Razor Halaman untuk kesalahan harus menerima nilai segmen jalur opsional dengan direktif @page :
@page "{code?}"
Titik akhir yang memproses kesalahan bisa mendapatkan URL asli yang menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
var statusCodeReExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature != null)
{
OriginalURL =
statusCodeReExecuteFeature.OriginalPathBase
+ statusCodeReExecuteFeature.OriginalPath
+ statusCodeReExecuteFeature.OriginalQueryString;
}
Jangan tandai metode tindakan penangan kesalahan dengan atribut metode HTTP, seperti HttpGet. Kata kerja eksplisit mencegah beberapa permintaan mencapai metode . Izinkan akses anonim ke metode jika pengguna yang tidak diaturentikasi akan melihat tampilan kesalahan.
Menonaktifkan halaman kode status
Untuk menonaktifkan halaman kode status untuk pengontrol MVC atau metode tindakan, gunakan [SkipStatusCodePages] atribut .
Untuk menonaktifkan halaman kode status untuk permintaan tertentu dalam Razor metode handler Pages atau di pengontrol MVC, gunakan IStatusCodePagesFeature:
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
Kode penanganan pengecualian
Kode dalam halaman penanganan pengecualian dapat melemparkan pengecualian. Seringkali disarankan agar halaman error produksi terdiri dari konten statis murni.
Tajuk respons
Setelah header untuk respons dikirim:
- Aplikasi tidak dapat mengubah kode status respons.
- Halaman pengecualian atau handler apa pun tidak dapat dijalankan. Respons harus diselesaikan atau koneksi dibatalkan.
Penanganan pengecualian server
Selain logika penanganan pengecualian di aplikasi Anda, implementasi server HTTP dapat menangani beberapa pengecualian. Jika server menangkap pengecualian sebelum header respons dikirim, server mengirimkan respons 500 - Kesalahan Server Internal tanpa badan respons. Jika server menangkap pengecualian setelah header respons dikirim, server menutup koneksi. Permintaan yang tidak ditangani oleh aplikasi Anda ditangani oleh server. Pengecualian apa pun yang terjadi ketika server menangani permintaan ditangani oleh penanganan pengecualian server. Halaman kesalahan kustom aplikasi, middleware penanganan pengecualian, dan filter tidak memengaruhi perilaku ini.
Penanganan pengecualian startup
Hanya lapisan hosting yang dapat menangani pengecualian yang terjadi selama startup aplikasi. Host dapat dikonfigurasi untuk menangkap kesalahan pada saat startup dan menangkap kesalahan yang terperinci.
Lapisan hosting dapat menampilkan halaman kesalahan untuk kesalahan startup yang terdeteksi hanya jika kesalahan terjadi setelah pengikatan alamat dan port host. Jika pengikatan gagal:
- Lapisan hosting mencatat pengecualian penting.
- Proses dotnet mengalami crash.
- Tidak ada halaman kesalahan yang ditampilkan ketika server HTTP adalah Kestrel.
Saat berjalan di IIS (atau Azure App Service) atau IIS Express, 502.5 - Kegagalan Proses dikembalikan oleh Modul ASP.NET Core jika proses tidak dapat dimulai. Untuk informasi selengkapnya, lihat Memecahkan masalah ASP.NET Core di Azure App Service dan IIS.
Halaman kesalahan database
Middleware Halaman Kesalahan Database menangkap pengecualian terkait database yang dapat diselesaikan dengan menggunakan migrasi Kerangka Kerja Entitas. Ketika pengecualian ini terjadi, respons HTML dengan detail kemungkinan tindakan untuk menyelesaikan masalah dihasilkan. Halaman ini harus diaktifkan hanya di lingkungan Pengembangan. Aktifkan halaman dengan menambahkan kode ke Startup.Configure:
if (env.IsDevelopment())
{
app.UseDatabaseErrorPage();
}
UseDatabaseErrorPage memerlukan paket NuGet Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.
Filter pengecualian
Di aplikasi MVC, filter pengecualian dapat dikonfigurasi secara global atau berdasarkan per pengontrol atau per tindakan. Di Razor aplikasi Pages, aplikasi tersebut dapat dikonfigurasi secara global atau per model halaman. Filter ini menangani pengecualian yang tidak tertangani yang terjadi selama eksekusi tindakan pengontrol atau filter lain. Untuk informasi selengkapnya, lihat Filter di ASP.NET Core.
Tip
Filter pengecualian berguna untuk menjebak pengecualian yang terjadi dalam tindakan MVC, tetapi tidak fleksibel seperti Middleware Penanganan Pengecualian. Sebaiknya gunakan middleware. Gunakan filter hanya di mana Anda perlu melakukan penanganan kesalahan secara berbeda berdasarkan tindakan MVC mana yang dipilih.
Kesalahan status model
Untuk informasi tentang cara menangani kesalahan status model, lihat Pengikatan model dan Validasi model.
Sumber daya tambahan
ASP.NET Core