Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Note
Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.
Warning
A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .
Ez a cikk az ASP.NET Core-webalkalmazásokban előforduló hibák kezelésének gyakori megközelítéseit ismerteti. Lásd még : ASP.NET Core API-k hibáinak kezelése.
A Blazor jelen cikkben szereplő útmutatást kiegészítő vagy felülíró hibakezelési útmutatásért lásd: ASP.NET Core-alkalmazások Blazor hibáinak kezelése.
Fejlesztői kivételoldal
A Fejlesztői kivétel lap részletes információkat jelenít meg a nem kezelt kérelmek kivételeiről. A HTTP-folyamat szinkron és aszinkron kivételeinek rögzítésére és hibaválaszok létrehozására használja DeveloperExceptionPageMiddleware . A fejlesztői kivételoldal a köztes szoftver folyamatának korai szakaszában fut, hogy a következő köztes szoftverben megjelenő kezeletlen kivételeket észlelhesse.
ASP.NET Core-alkalmazások alapértelmezés szerint engedélyezik a fejlesztői kivételoldalt, ha mindkettő:
- Futtatás a fejlesztési környezetben.
- Az alkalmazás az aktuális sablonok, azaz a WebApplication.CreateBuilder használatával jött létre.
A korábbi sablonokkal, azaz a WebHost.CreateDefaultBuilder sablon használatával létrehozott alkalmazások a app.UseDeveloperExceptionPage függvény hívásával engedélyezhetik a fejlesztői kivételoldalt.
Warning
Csak akkor engedélyezze a fejlesztői kivételoldalt, ha az alkalmazás a fejlesztői környezetben fut. Ne ossza meg nyilvánosan a részletes kivételadatokat, ha az alkalmazás éles környezetben fut. További információ a környezetek konfigurálásáról: ASP.NET Core futtatókörnyezetek.
A Fejlesztői kivétel lap a következő információkat tartalmazhatja a kivételről és a kérésről:
- Verem nyomkövetése
- Lekérdezési sztringparaméterek, ha vannak ilyenek
- Cookie-k, ha vannak ilyenek
- Headers
- Végpont metaadatai, ha vannak ilyenek
A fejlesztői kivételoldal nem garantáltan biztosít semmilyen információt. Használja a naplózást a teljes hibainformációkhoz.
Az alábbi képen egy minta fejlesztői kivétellap látható, amelyen animáció látható a lapok és a megjelenített információk megjelenítéséhez:
Egy fejlécet tartalmazó Accept: text/plain kérésre válaszul a Fejlesztői kivételoldal a HTML helyett egyszerű szöveget ad vissza. Például:
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
Kivételkezelő lap
Ha egyéni hibakezelő lapot szeretne konfigurálni az éles környezethez, hívja meg a következőt UseExceptionHandler: . Ez a kivételkezelés köztes szoftver:
- Naplózza a kezeletlen kivételeket.
- A kérést újra végrehajtja egy másik folyamatban a megadott elérési út használatával. A rendszer nem hajtja végre újra a kérést, ha a válasz elindult. A sablon által létrehozott kód újra végrehajtja a kérést az
/Errorelérési út használatával.
Warning
Ha az alternatív csővezeték saját kivételt dob, a Kivételkezelő köztes réteg újradobja az eredeti kivételt.
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - UseExceptionHandler(IApplicationBuilder, String) A sablonokban használt túlterhelés esetén csak a kérelem útvonala módosul, és az útvonaladatok törlődnek. A kérelemadatok, például a fejlécek, a metódusok és az elemek mind újra felhasználhatók as-is.
- A hatókörön belüli szolgáltatások változatlanok maradnak.
Az alábbi példában a UseExceptionHandler hozzáadja a kivételkezelő middleware-t a fejlesztési környezeteken kívüli környezetekben.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
A Razor Lapok alkalmazássablon egy Hibalapot (.cshtml) és PageModel osztályt (ErrorModel) biztosít a Lapok mappában. MVC-alkalmazások esetén a projektsablon tartalmaz egy Error műveletmetódust és egy hibanézetet a Home vezérlőhöz.
A köztes szoftver kivételkezelése újra végrehajtja a kérést az eredeti HTTP-módszerrel. Ha egy hibakezelő végpont a HTTP-metódusok egy meghatározott halmazára korlátozódik, az csak az adott HTTP-metódusokhoz fut. Az attribútumot használó [HttpGet] MVC-vezérlőművelet például csak GET-kérelmek esetén fut. Annak érdekében, hogy minden kérés elérje az egyéni hibakezelő lapot, ne korlátozza azokat a HTTP-metódusok meghatározott készletére.
A kivételek eltérő kezelése az eredeti HTTP-módszer alapján:
- A Razor Pages esetében hozzon létre több kezelő metódusokat. Például a
OnGeta GET-kivételek kezelésére, míg aOnPosta POST-kivételek kezelésére használható. - MVC esetén http-igeattribútumokat alkalmazhat több műveletre. Például a
[HttpGet]a GET-kivételek kezelésére, míg a[HttpPost]a POST-kivételek kezelésére használható.
Ha engedélyezni szeretné, hogy a hitelesítés nélküli felhasználók megtekinthessék az egyéni hibakezelő lapot, győződjön meg arról, hogy támogatja a névtelen hozzáférést.
A kivétel elérése
Használja a IExceptionHandlerPathFeature elemet a kivétel és az eredeti kérési útvonal elérésére egy hibakezelőben. Az alábbi példa IExceptionHandlerPathFeature a kidobott kivételről nyújt további információt:
[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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
Kivételkezelő lambda
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését a válasz visszaadása előtt.
A következő kód egy lambdát használ a kivételkezeléshez:
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();
}
A lambda használatának másik módja, ha az állapotkódot a kivétel típusa alapján állítja be, ahogyan az alábbi példában is látható:
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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
IExceptionHandler
Az IExceptionHandler egy olyan felület, amely visszahívást biztosít a fejlesztőnek az ismert kivételek központi helyen való kezelésére. Az interfész egyetlen metódust tartalmaz, TryHandleAsync, amely egy HttpContext és egy Exception paramétert kap.
IExceptionHandler implementációkat a IServiceCollection.AddExceptionHandler<T>meghívásával regisztrálják. Az IExceptionHandler példány élettartama singleton. Több implementáció is hozzáadható, és a rendszer a regisztrált sorrendben hívja meg őket.
A köztes szoftver kivételkezelése a regisztrált kivételkezelőkön keresztül halad végig sorrendben, amíg az egyik vissza nem tér true a TryHandleAsync-ből, jelezve, hogy a kivétel el volt kezelve. Ha egy kivételkezelő kezel egy kivételt, visszatérhet true a feldolgozás leállításához. Ha egy kivételt egyetlen kivételkezelő sem kezel, akkor a vezérlés visszaesik a köztes szoftver alapértelmezett viselkedésére és beállításaira.
A .NET 10-től kezdve az alapértelmezett viselkedés az, hogy letiltja a diagnosztikák, például a naplók és metrikák kibocsátását, amikor a kezelt kivételek TryHandleAsync visszaadják a true értéket. Ez eltér a korábbi verzióktól (.NET 8 és 9), ahol a diagnosztika mindig ki lett bocsátva, függetlenül attól, hogy a kivételt kezelték-e. Az alapértelmezett viselkedés a SuppressDiagnosticsCallback beállítással módosítható.
Az alábbi példa egy implementációt IExceptionHandler mutat be:
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);
}
}
}
Az alábbi példa bemutatja, hogyan regisztrálhat implementációt IExceptionHandler függőséginjektáláshoz:
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
Ha az előző kód a fejlesztési környezetben fut:
- A
CustomExceptionHandlerelőször meghívódik a kivétel kezelésére. - A kivétel naplózása után a
TryHandleAsyncmetódus visszatérfalse, így megjelenik a fejlesztői kivétellap.
Más környezetekben:
- A
CustomExceptionHandlerelőször meghívódik a kivétel kezelésére. - A kivétel naplózása után a
TryHandleAsyncmetódus visszatér, így megjelenikfalseaz/Erroroldal .
SuppressDiagnosticsCallback
A .NET 10-től elkezdve szabályozhatja, hogy az exception handling middleware diagnosztikákat ír-e a kezelt kivételekről azzal, hogy beállítja a SuppressDiagnosticsCallback tulajdonságot a ExceptionHandlerOptions elemen. Ez a visszahívás megkapja a kivétel kontextusát, és lehetővé teszi annak meghatározását, hogy a diagnosztika mellőzhető-e az adott kivétel vagy kérés alapján.
Ha vissza szeretne térni a .NET 8 és 9 viselkedésére, ahol a diagnosztika mindig kiváltásra kerül a kezelt kivételek esetében, állítsa úgy be a visszahívást, hogy az mindig visszaadja a következőt: false.
app.UseExceptionHandler(new ExceptionHandlerOptions
{
SuppressDiagnosticsCallback = context => false
});
A diagnosztika feltételesen letiltható a kivétel típusa vagy más környezet alapján is:
app.UseExceptionHandler(new ExceptionHandlerOptions
{
SuppressDiagnosticsCallback = context => context.Exception is ArgumentException
});
Ha egy kivételt semmilyen implementáció nem kezel IExceptionHandler (minden kezelő visszatér falseTryHandleAsync), a vezérlés visszaáll a köztes szoftver alapértelmezett viselkedésére és beállításaira, és a rendszer a köztes szoftver szokásos viselkedésének megfelelően bocsát ki diagnosztikát.
UseStatusCodePages
Alapértelmezés szerint egy ASP.NET Core-alkalmazás nem biztosít állapotkódlapot a HTTP-hibaállapot-kódokhoz, például 404 – Nem található. Amikor az alkalmazás beállít egy HTTP 400-599 hibaállapot-kódot, amely nem tartalmaz törzset, az állapotkódot és egy üres választörzset ad vissza. Ha engedélyezni szeretné az alapértelmezett csak szöveges kezelőket a gyakori hibaállapot-kódokhoz, hívja meg UseStatusCodePages a Program.cs-ben:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Hívás UseStatusCodePages a köztes szoftverrel kapcsolatos kérések kezelése előtt. Hívja például a UseStatusCodePages parancsot a statikus fájlok köztes rétege és az Endpoints Middleware előtt.
Ha UseStatusCodePages nincs használatban, a végpont nélküli URL-címre való navigálás egy böngészőfüggő hibaüzenetet ad vissza, amely jelzi, hogy a végpont nem található. Amikor UseStatusCodePages a rendszer meghívja, a böngésző a következő választ adja vissza:
Status Code: 404; Not Found
UseStatusCodePages általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
Note
Az állapotkódlapok köztes szoftverei nem észlelnek kivételeket. Egyéni hibakezelő lap megadásához használja a kivételkezelő lapot.
UseStatusCodePages formátum sztring alkalmazásával
A válasz tartalomtípusának és szövegének testreszabásához használja azt a UseStatusCodePages túlterhelést, amely tartalomtípust és formázási sztringet vesz fel.
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}");
Az előző kódban a {0} egy helyőrző a hibakód számára.
UseStatusCodePages a formátumsztringet általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePages a lambda kifejezéssel
Az egyéni hibakezelési és válaszírási kód megadásához használja az UseStatusCodePages azon túlterhelését, amely elfogad egy lambda kifejezést:
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}");
});
A lambdát általában nem használják termelési környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePagesWithRedirects
A UseStatusCodePagesWithRedirects bővítmény metódusa:
- 302 – Talált állapotkódot küld az ügyfélnek.
- Átirányítja az ügyfelet az URL-sablonban megadott hibakezelési végpontra. A hibakezelő végpont általában hibainformációkat jelenít meg, és HTTP 200-et ad vissza.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Az URL-sablon tartalmazhat helyőrzőt {0} az állapotkódhoz, ahogyan az az előző kódban is látható. Ha az URL-sablon ~ (tilde) jellel kezdődik ~, akkor az ~ helyébe az alkalmazás PathBase kerül. Amikor végpontot ad meg az alkalmazásban, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják az alkalmazás esetében:
- Az ügyfelet egy másik végpontra kell átirányítani, általában olyan esetekben, amikor egy másik alkalmazás feldolgozza a hibát. Webalkalmazások esetén az ügyfél böngészőcímsávja az átirányított végpontot tükrözi.
- Ne őrizze meg és ne adja vissza az eredeti állapotkódot az első átirányítási válasznál.
UseStatusCodePagesWithReExecute
A UseStatusCodePagesWithReExecute bővítmény metódusa:
- A válasz törzsét úgy hozza létre, hogy egy másik elérési út használatával újra végrehajtja a kérelemfolyamatot.
- Nem módosítja az állapotkódot a folyamat ismételt végrehajtása előtt vagy után.
Az új folyamat végrehajtása megváltoztathatja a válasz állapotkódját, mivel az új folyamat teljes mértékben szabályozza az állapotkódot. Ha az új folyamat nem módosítja az állapotkódot, a rendszer elküldi az eredeti állapotkódot az ügyfélnek.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Ha az alkalmazásban egy végpont van megadva, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják, amikor az alkalmazásnak a következőt kell használnia:
- A kérés feldolgozása egy másik végpontra való átirányítás nélkül. Webalkalmazások esetén az ügyfél böngészőcímsávja az eredetileg kért végpontot tükrözi.
- Őrizze meg és adja vissza az eredeti állapotkódot a válaszsal együtt.
Az URL-sablonnak kezdődnie kell, / és tartalmaznia kell egy helyőrzőt {0} az állapotkódhoz. Ha az állapotkódot lekérdezési sztring paraméterként szeretné átadni, adjon át egy második argumentumot a következőbe UseStatusCodePagesWithReExecute: Például:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
A hibát feldolgozó végpont lekérheti a hibát létrehozó eredeti URL-címet, ahogyan az az alábbi példában látható:
[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}";
}
}
}
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - A hatókörön belüli szolgáltatások változatlanok maradnak.
Állapotkódlapok letiltása
MVC-vezérlő vagy műveleti metódus állapotkódlapjainak letiltásához használja a [SkipStatusCodePages] attribútumot.
Ha le szeretné tiltani az állapotkódlapokat a Razor Pages-kezelő metódusban vagy egy MVC-vezérlőben megadott kérésekhez, használja a következőt IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kivételkezelési kód
A kivételkezelő lapok kódjai kivételeket is okozhatnak. A gyártási hibaoldalakat alaposan tesztelni kell, és fokozottan ügyelni kell arra, hogy elkerüljük a sajátjaik által okozott kivételeket.
Válaszfejlécek
A válasz fejléceinek elküldése után:
- Az alkalmazás nem tudja módosítani a válasz állapotkódját.
- A kivételoldalak vagy -kezelők nem futtathatók. A választ be kell fejezni, vagy megszakadt a kapcsolat.
Kiszolgálói kivételkezelés
Az alkalmazások kivételkezelési logikája mellett a HTTP-kiszolgáló implementációja is képes kezelni néhány kivételt. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése előtt, a kiszolgáló választörzs nélkül küld 500 - Internal Server Error választ. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése után, a kiszolgáló bezárja a kapcsolatot. Az alkalmazás által nem kezelt kérelmeket a kiszolgáló kezeli. Minden kivételt, amely akkor fordul elő, amikor a kiszolgáló kezeli a kérést, a kiszolgáló kivételkezelése kezeli. Az alkalmazás egyéni hibaoldalai, a köztes szoftver kivételkezelése és a szűrők nem befolyásolják ezt a viselkedést.
Indítási kivétel kezelése
Csak az üzemeltetési réteg képes kezelni az alkalmazás indításakor előforduló kivételeket. A gazdagép konfigurálható az indítási hibák és a részletes hibák rögzítésére.
A fogadó réteg csak akkor jeleníthet meg hibalapot egy észlelt indítási hiba esetén, ha a hiba a gazdacím/port kötése után következik be. Ha a kötés sikertelen:
- Az üzemeltetési réteg kritikus kivételt naplóz.
- A dotnet-folyamat összeomlik.
- HTTP-kiszolgáló Kestrel állapotában nem jelenik meg hibaoldal.
Ha IIS-en (vagy Azure App Service-en) vagy IIS Expressen fut, az ASP.NET core modul502.5-ös folyamathibát ad vissza, ha a folyamat nem indítható el. További információ: ASP.NET Core hibaelhárítása az Azure App Service-ben és az IIS-ben.
Adatbázis hibaoldala
Az adatbázis fejlesztői lapjának kivételszűrője AddDatabaseDeveloperPageExceptionFilter rögzíti az adatbázissal kapcsolatos kivételeket, amelyek az Entity Framework Core migrálásával oldhatók meg. Ha ezek a kivételek előfordulnak, a rendszer HTML-választ hoz létre a probléma megoldásához szükséges lehetséges műveletek részleteivel. Ez a lap csak a fejlesztési környezetben engedélyezett. A következő kód hozzáadja az Adatbázis fejlesztői oldal kivételszűrőjét:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Kivételszűrők
Az MVC-alkalmazásokban a kivételszűrők globálisan, vezérlőnként vagy műveletenként konfigurálhatók. A Razor Pages-alkalmazásokban globálisan vagy oldalmodellenként konfigurálhatók. Ezek a szűrők kezelik a vezérlőművelet vagy egy másik szűrő végrehajtása során előforduló nem kezelt kivételeket. További információ: Szűrők a ASP.NET Core-ban.
A kivételszűrők hasznosak az MVC-műveletekben előforduló kivételek csapdába ejtéséhez, de nem olyan rugalmasak, mint a beépített kivételkezelő köztes szoftver, UseExceptionHandler. Javasoljuk, hogy használja UseExceptionHandler, kivéve, ha a hibakezelést a választott MVC-művelet alapján eltérő módon kell elvégeznie.
Modellállapot-hibák
A modellállapot-hibák kezelésével kapcsolatos információkért tekintse meg a modellkötést és a modellérvényesítést ismertető témakört.
Probléma részletei
A probléma részletei nem az egyetlen válaszformátum a HTTP API-hibák leírásához, azonban gyakran használják őket a HTTP API-k hibáinak jelentésére.
A probléma részletei szolgáltatás implementálja a felületet, amely támogatja a IProblemDetailsService probléma részleteinek létrehozását a ASP.NET Core-ban. A AddProblemDetails(IServiceCollection) bővítménymetódus a IServiceCollection regisztrálja az alapértelmezett IProblemDetailsService implementációt.
A ASP.NET Core-alkalmazásokban a következő köztes szoftver generálja a probléma részleteit HTTP-válaszok meghívásakorAddProblemDetails, kivéve, ha a Accept kérelem HTTP-fejléce nem tartalmazza a regisztrált IProblemDetailsWriter (alapértelmezett) által támogatott tartalomtípusokat: application/json
- ExceptionHandlerMiddleware: Probléma részleteit tartalmazó választ hoz létre, ha nincs definiálva egyéni kezelő.
- StatusCodePagesMiddleware: Alapértelmezés szerint létrehoz egy probléma részleteit tartalmazó választ.
-
DeveloperExceptionPageMiddleware: Probléma részleteit tartalmazó választ hoz létre a fejlesztési környezetben, amikor a kérelem HTTP-fejléce nem tartalmazza a
Acceptértéket.
Az alábbi kód úgy konfigurálja az alkalmazást, hogy probléma részleteit adja meg az összes olyan HTTP-ügyfél- és kiszolgálóhiba-válaszhoz, amely még nem rendelkezik törzstartalommal:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
A következő szakasz bemutatja, hogyan szabhatja testre a probléma részleteit tartalmazó választörzset.
A probléma részleteinek testreszabása
Az ProblemDetails automatikus létrehozása az alábbi lehetőségek bármelyikével testre szabható.
- Használja a
ProblemDetailsOptions.CustomizeProblemDetails-t - Egyéni
IProblemDetailsWriterhasználata -
Hívja a
IProblemDetailsServiceköztes szoftvert
CustomizeProblemDetails művelet
A létrehozott probléma részletei testre szabhatók a használatával CustomizeProblemDetails, és a testreszabások az automatikusan létrehozott probléma részleteire lesznek alkalmazva.
A beállításhoz ProblemDetailsOptionsa következő kód szolgálCustomizeProblemDetails:
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();
Például egy HTTP Status 400 Bad Request végpont eredménye a következő probléma részletei választ ad vissza:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Egyéni IProblemDetailsWriter
A IProblemDetailsWriter implementáció létrehozható a speciális testreszabásokhoz.
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));
}
}
Jegyzet: Egyéni IProblemDetailsWriter használata esetén a hívás IProblemDetailsWriter előtt regisztrálni kell az egyénit AddRazorPages, AddControllers, AddControllersWithViews, vagy 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();
A Middleware-ből származó probléma részletei
Az ProblemDetailsOptions és CustomizeProblemDetails használatának egyik alternatív módszere, hogy a ProblemDetails-t köztes rétegben állítjuk be. A probléma részleteire adott választ a következő hívással IProblemDetailsService.WriteAsynclehet megírni:
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();
Az előző kódban a minimális API-végpontok /divide , és /squareroot a várt egyéni hibaválaszt adja vissza a hibabemenethez.
Az API-vezérlő végpontjai az alapértelmezett hibaválaszt adják vissza a hibabemenetkor, nem pedig az egyéni problémamegoldást. A rendszer az alapértelmezett problémaválaszt adja vissza, mert az API-vezérlő a válaszstreambe írt a hibaállapotkódokkal kapcsolatos problémák részleteit, mielőtt IProblemDetailsService.WriteAsync meghívták, és a válasz nem íródik újra.
Az alábbi ValuesController visszaadja BadRequestResult, ami a válaszfolyamba ír, és így megakadályozza az egyéni probléma válaszának visszatérését.
[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));
}
}
A következő Values3Controller a ControllerBase.Problem eredményt adja vissza, így a várt egyéni probléma eredménye lesz:
[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));
}
}
Hozzon létre egy ProblemDetails adatcsomagot a kivételekhez
Fontolja meg a következő alkalmazást:
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();
Nem fejlesztési környezetekben, ha kivétel történik, a következő egy szabványos ProblemDetails-válasz , amelyet a rendszer visszaad az ügyfélnek:
{
"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"
}
A legtöbb alkalmazás esetében csak az előző kód szükséges a kivételekhez. Az alábbi szakasz azonban bemutatja, hogyan kaphat részletesebb választ a problémákra.
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését és a probléma részleteit tartalmazó válasz megírását a következővel 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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
A probléma részleteinek létrehozására másik módszer a külső NuGet-csomag, a Hellang.Middleware.ProblemDetails használata, amely a kivételek és az ügyfélhibák leképezésére használható a probléma részleteire.
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
- Az Azure App Service és az IIS ASP.NET Core hibaelhárítása
- Gyakori hibák elhárítása az Azure App Service-ben és az IIS-ben az ASP.NET Core esetén
- ASP.NET Core API-k hibáinak kezelése
-
Kompatibilitástörő változás: A kivételdiagnosztikát a rendszer letiltja, ha
IExceptionHandler.TryHandleAsyncigaz értéket ad vissza
Ez a cikk az ASP.NET Core-webalkalmazásokban előforduló hibák kezelésének gyakori megközelítéseit ismerteti. Lásd még : ASP.NET Core API-k hibáinak kezelése.
A Blazor jelen cikkben szereplő útmutatást kiegészítő vagy felülíró hibakezelési útmutatásért lásd: ASP.NET Core-alkalmazások Blazor hibáinak kezelése.
Fejlesztői kivételoldal
A Fejlesztői kivétel lap részletes információkat jelenít meg a nem kezelt kérelmek kivételeiről. A HTTP-folyamat szinkron és aszinkron kivételeinek rögzítésére és hibaválaszok létrehozására használja DeveloperExceptionPageMiddleware . A fejlesztői kivételoldal a köztes szoftver folyamatának korai szakaszában fut, hogy a következő köztes szoftverben megjelenő kezeletlen kivételeket észlelhesse.
ASP.NET Core-alkalmazások alapértelmezés szerint engedélyezik a fejlesztői kivételoldalt, ha mindkettő:
- Futtatás a fejlesztési környezetben.
- Az alkalmazás az aktuális sablonok, azaz a WebApplication.CreateBuilder használatával jött létre.
A korábbi sablonokkal, azaz a WebHost.CreateDefaultBuilder sablon használatával létrehozott alkalmazások a app.UseDeveloperExceptionPage függvény hívásával engedélyezhetik a fejlesztői kivételoldalt.
Warning
Csak akkor engedélyezze a fejlesztői kivételoldalt, ha az alkalmazás a fejlesztői környezetben fut. Ne ossza meg nyilvánosan a részletes kivételadatokat, ha az alkalmazás éles környezetben fut. További információ a környezetek konfigurálásáról: ASP.NET Core futtatókörnyezetek.
A Fejlesztői kivétel lap a következő információkat tartalmazhatja a kivételről és a kérésről:
- Verem nyomkövetése
- Lekérdezési sztringparaméterek, ha vannak ilyenek
- Cookie-k, ha vannak ilyenek
- Headers
- Végpont metaadatai, ha vannak ilyenek
A fejlesztői kivételoldal nem garantáltan biztosít semmilyen információt. Használja a naplózást a teljes hibainformációkhoz.
Az alábbi képen egy minta fejlesztői kivétellap látható, amelyen animáció látható a lapok és a megjelenített információk megjelenítéséhez:
Egy fejlécet tartalmazó Accept: text/plain kérésre válaszul a Fejlesztői kivételoldal a HTML helyett egyszerű szöveget ad vissza. Például:
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
Kivételkezelő lap
Ha egyéni hibakezelő lapot szeretne konfigurálni az éles környezethez, hívja meg a következőt UseExceptionHandler: . Ez a kivételkezelés köztes szoftver:
- Naplózza a kezeletlen kivételeket.
- A kérést újra végrehajtja egy másik folyamatban a megadott elérési út használatával. A rendszer nem hajtja végre újra a kérést, ha a válasz elindult. A sablon által létrehozott kód újra végrehajtja a kérést az
/Errorelérési út használatával.
Warning
Ha az alternatív csővezeték saját kivételt dob, a Kivételkezelő köztes réteg újradobja az eredeti kivételt.
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - UseExceptionHandler(IApplicationBuilder, String) A sablonokban használt túlterhelés esetén csak a kérelem útvonala módosul, és az útvonaladatok törlődnek. A kérelemadatok, például a fejlécek, a metódusok és az elemek mind újra felhasználhatók as-is.
- A hatókörön belüli szolgáltatások változatlanok maradnak.
Az alábbi példában a UseExceptionHandler hozzáadja a kivételkezelő middleware-t a fejlesztési környezeteken kívüli környezetekben.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
A Razor Lapok alkalmazássablon egy Hibalapot (.cshtml) és PageModel osztályt (ErrorModel) biztosít a Lapok mappában. MVC-alkalmazások esetén a projektsablon tartalmaz egy Error műveletmetódust és egy hibanézetet a Home vezérlőhöz.
A köztes szoftver kivételkezelése újra végrehajtja a kérést az eredeti HTTP-módszerrel. Ha egy hibakezelő végpont a HTTP-metódusok egy meghatározott halmazára korlátozódik, az csak az adott HTTP-metódusokhoz fut. Az attribútumot használó [HttpGet] MVC-vezérlőművelet például csak GET-kérelmek esetén fut. Annak érdekében, hogy minden kérés elérje az egyéni hibakezelő lapot, ne korlátozza azokat a HTTP-metódusok meghatározott készletére.
A kivételek eltérő kezelése az eredeti HTTP-módszer alapján:
- A Razor Pages esetében hozzon létre több kezelő metódusokat. Például a
OnGeta GET-kivételek kezelésére, míg aOnPosta POST-kivételek kezelésére használható. - MVC esetén http-igeattribútumokat alkalmazhat több műveletre. Például a
[HttpGet]a GET-kivételek kezelésére, míg a[HttpPost]a POST-kivételek kezelésére használható.
Ha engedélyezni szeretné, hogy a hitelesítés nélküli felhasználók megtekinthessék az egyéni hibakezelő lapot, győződjön meg arról, hogy támogatja a névtelen hozzáférést.
A kivétel elérése
Használja a IExceptionHandlerPathFeature elemet a kivétel és az eredeti kérési útvonal elérésére egy hibakezelőben. Az alábbi példa IExceptionHandlerPathFeature a kidobott kivételről nyújt további információt:
[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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
Kivételkezelő lambda
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését a válasz visszaadása előtt.
A következő kód egy lambdát használ a kivételkezeléshez:
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();
}
A lambda használatának másik módja, ha az állapotkódot a kivétel típusa alapján állítja be, ahogyan az alábbi példában is látható:
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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
IExceptionHandler
Az IExceptionHandler egy olyan felület, amely visszahívást biztosít a fejlesztőnek az ismert kivételek központi helyen való kezelésére.
IExceptionHandler implementációkat a IServiceCollection.AddExceptionHandler<T>meghívásával regisztrálják. Az IExceptionHandler példány élettartama singleton. Több implementáció is hozzáadható, és a rendszer a regisztrált sorrendben hívja meg őket.
Ha egy kivételkezelő kezel egy kérést, true adhat vissza a feldolgozás leállításához. Ha egy kivételt egyetlen kivételkezelő sem kezel, akkor a vezérlés visszaesik a köztes szoftver alapértelmezett viselkedésére és beállításaira. Különböző metrikákat és naplókat bocsát ki a rendszer a kezelt és kezeletlen kivételek esetén.
Az alábbi példa egy implementációt IExceptionHandler mutat be:
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);
}
}
}
Az alábbi példa bemutatja, hogyan regisztrálhat implementációt IExceptionHandler függőséginjektáláshoz:
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
Ha az előző kód a fejlesztési környezetben fut:
- A
CustomExceptionHandlerelőször meghívódik a kivétel kezelésére. - A kivétel naplózása után a
TryHandleAsyncmetódus visszatérfalse, így megjelenik a fejlesztői kivétellap.
Más környezetekben:
- A
CustomExceptionHandlerelőször meghívódik a kivétel kezelésére. - A kivétel naplózása után a
TryHandleAsyncmetódus visszatér, így megjelenikfalseaz/Erroroldal .
UseStatusCodePages
Alapértelmezés szerint egy ASP.NET Core-alkalmazás nem biztosít állapotkódlapot a HTTP-hibaállapot-kódokhoz, például 404 – Nem található. Amikor az alkalmazás beállít egy HTTP 400-599 hibaállapot-kódot, amely nem tartalmaz törzset, az állapotkódot és egy üres választörzset ad vissza. Ha engedélyezni szeretné az alapértelmezett csak szöveges kezelőket a gyakori hibaállapot-kódokhoz, hívja meg UseStatusCodePages a Program.cs-ben:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Hívás UseStatusCodePages a köztes szoftverrel kapcsolatos kérések kezelése előtt. Hívja például a UseStatusCodePages parancsot a statikus fájlok köztes rétege és az Endpoints Middleware előtt.
Ha UseStatusCodePages nincs használatban, a végpont nélküli URL-címre való navigálás egy böngészőfüggő hibaüzenetet ad vissza, amely jelzi, hogy a végpont nem található. Amikor UseStatusCodePages a rendszer meghívja, a böngésző a következő választ adja vissza:
Status Code: 404; Not Found
UseStatusCodePages általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
Note
Az állapotkódlapok köztes szoftverei nem észlelnek kivételeket. Egyéni hibakezelő lap megadásához használja a kivételkezelő lapot.
UseStatusCodePages formátum sztring alkalmazásával
A válasz tartalomtípusának és szövegének testreszabásához használja azt a UseStatusCodePages túlterhelést, amely tartalomtípust és formázási sztringet vesz fel.
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}");
Az előző kódban a {0} egy helyőrző a hibakód számára.
UseStatusCodePages a formátumsztringet általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePages a lambda kifejezéssel
Az egyéni hibakezelési és válaszírási kód megadásához használja az UseStatusCodePages azon túlterhelését, amely elfogad egy lambda kifejezést:
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}");
});
A lambdát általában nem használják termelési környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePagesWithRedirects
A UseStatusCodePagesWithRedirects bővítmény metódusa:
- 302 – Talált állapotkódot küld az ügyfélnek.
- Átirányítja az ügyfelet az URL-sablonban megadott hibakezelési végpontra. A hibakezelő végpont általában hibainformációkat jelenít meg, és HTTP 200-et ad vissza.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Az URL-sablon tartalmazhat helyőrzőt {0} az állapotkódhoz, ahogyan az az előző kódban is látható. Ha az URL-sablon ~ (tilde) jellel kezdődik ~, akkor az ~ helyébe az alkalmazás PathBase kerül. Amikor végpontot ad meg az alkalmazásban, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják az alkalmazás esetében:
- Az ügyfelet egy másik végpontra kell átirányítani, általában olyan esetekben, amikor egy másik alkalmazás feldolgozza a hibát. Webalkalmazások esetén az ügyfél böngészőcímsávja az átirányított végpontot tükrözi.
- Ne őrizze meg és ne adja vissza az eredeti állapotkódot az első átirányítási válasznál.
UseStatusCodePagesWithReExecute
A UseStatusCodePagesWithReExecute bővítmény metódusa:
- A válasz törzsét úgy hozza létre, hogy egy másik elérési út használatával újra végrehajtja a kérelemfolyamatot.
- Nem módosítja az állapotkódot a folyamat ismételt végrehajtása előtt vagy után.
Az új folyamat végrehajtása megváltoztathatja a válasz állapotkódját, mivel az új folyamat teljes mértékben szabályozza az állapotkódot. Ha az új folyamat nem módosítja az állapotkódot, a rendszer elküldi az eredeti állapotkódot az ügyfélnek.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Ha az alkalmazásban egy végpont van megadva, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják, amikor az alkalmazásnak a következőt kell használnia:
- A kérés feldolgozása egy másik végpontra való átirányítás nélkül. Webalkalmazások esetén az ügyfél böngészőcímsávja az eredetileg kért végpontot tükrözi.
- Őrizze meg és adja vissza az eredeti állapotkódot a válaszsal együtt.
Az URL-sablonnak kezdődnie kell, / és tartalmaznia kell egy helyőrzőt {0} az állapotkódhoz. Ha az állapotkódot lekérdezési sztring paraméterként szeretné átadni, adjon át egy második argumentumot a következőbe UseStatusCodePagesWithReExecute: Például:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
A hibát feldolgozó végpont lekérheti a hibát létrehozó eredeti URL-címet, ahogyan az az alábbi példában látható:
[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}";
}
}
}
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - A hatókörön belüli szolgáltatások változatlanok maradnak.
Állapotkódlapok letiltása
MVC-vezérlő vagy műveleti metódus állapotkódlapjainak letiltásához használja a [SkipStatusCodePages] attribútumot.
Ha le szeretné tiltani az állapotkódlapokat a Razor Pages-kezelő metódusban vagy egy MVC-vezérlőben megadott kérésekhez, használja a következőt IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kivételkezelési kód
A kivételkezelő lapok kódjai kivételeket is okozhatnak. A gyártási hibaoldalakat alaposan tesztelni kell, és fokozottan ügyelni kell arra, hogy elkerüljük a sajátjaik által okozott kivételeket.
Válaszfejlécek
A válasz fejléceinek elküldése után:
- Az alkalmazás nem tudja módosítani a válasz állapotkódját.
- A kivételoldalak vagy -kezelők nem futtathatók. A választ be kell fejezni, vagy megszakadt a kapcsolat.
Kiszolgálói kivételkezelés
Az alkalmazások kivételkezelési logikája mellett a HTTP-kiszolgáló implementációja is képes kezelni néhány kivételt. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése előtt, a kiszolgáló választörzs nélkül küld 500 - Internal Server Error választ. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése után, a kiszolgáló bezárja a kapcsolatot. Az alkalmazás által nem kezelt kérelmeket a kiszolgáló kezeli. Minden kivételt, amely akkor fordul elő, amikor a kiszolgáló kezeli a kérést, a kiszolgáló kivételkezelése kezeli. Az alkalmazás egyéni hibaoldalai, a köztes szoftver kivételkezelése és a szűrők nem befolyásolják ezt a viselkedést.
Indítási kivétel kezelése
Csak az üzemeltetési réteg képes kezelni az alkalmazás indításakor előforduló kivételeket. A gazdagép konfigurálható az indítási hibák és a részletes hibák rögzítésére.
A fogadó réteg csak akkor jeleníthet meg hibalapot egy észlelt indítási hiba esetén, ha a hiba a gazdacím/port kötése után következik be. Ha a kötés sikertelen:
- Az üzemeltetési réteg kritikus kivételt naplóz.
- A dotnet-folyamat összeomlik.
- HTTP-kiszolgáló Kestrel állapotában nem jelenik meg hibaoldal.
Ha IIS-en (vagy Azure App Service-en) vagy IIS Expressen fut, az ASP.NET core modul502.5-ös folyamathibát ad vissza, ha a folyamat nem indítható el. További információ: ASP.NET Core hibaelhárítása az Azure App Service-ben és az IIS-ben.
Adatbázis hibaoldala
Az adatbázis fejlesztői lapjának kivételszűrője AddDatabaseDeveloperPageExceptionFilter rögzíti az adatbázissal kapcsolatos kivételeket, amelyek az Entity Framework Core migrálásával oldhatók meg. Ha ezek a kivételek előfordulnak, a rendszer HTML-választ hoz létre a probléma megoldásához szükséges lehetséges műveletek részleteivel. Ez a lap csak a fejlesztési környezetben engedélyezett. A következő kód hozzáadja az Adatbázis fejlesztői oldal kivételszűrőjét:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Kivételszűrők
Az MVC-alkalmazásokban a kivételszűrők globálisan, vezérlőnként vagy műveletenként konfigurálhatók. A Razor Pages-alkalmazásokban globálisan vagy oldalmodellenként konfigurálhatók. Ezek a szűrők kezelik a vezérlőművelet vagy egy másik szűrő végrehajtása során előforduló nem kezelt kivételeket. További információ: Szűrők a ASP.NET Core-ban.
A kivételszűrők hasznosak az MVC-műveletekben előforduló kivételek csapdába ejtéséhez, de nem olyan rugalmasak, mint a beépített kivételkezelő köztes szoftver, UseExceptionHandler. Javasoljuk, hogy használja UseExceptionHandler, kivéve, ha a hibakezelést a választott MVC-művelet alapján eltérő módon kell elvégeznie.
Modellállapot-hibák
A modellállapot-hibák kezelésével kapcsolatos információkért tekintse meg a modellkötést és a modellérvényesítést ismertető témakört.
Probléma részletei
A probléma részletei nem az egyetlen válaszformátum a HTTP API-hibák leírásához, azonban gyakran használják őket a HTTP API-k hibáinak jelentésére.
A probléma részletei szolgáltatás implementálja a felületet, amely támogatja a IProblemDetailsService probléma részleteinek létrehozását a ASP.NET Core-ban. A AddProblemDetails(IServiceCollection) bővítménymetódus a IServiceCollection regisztrálja az alapértelmezett IProblemDetailsService implementációt.
A ASP.NET Core-alkalmazásokban a következő köztes szoftver generálja a probléma részleteit HTTP-válaszok meghívásakorAddProblemDetails, kivéve, ha a Accept kérelem HTTP-fejléce nem tartalmazza a regisztrált IProblemDetailsWriter (alapértelmezett) által támogatott tartalomtípusokat: application/json
- ExceptionHandlerMiddleware: Probléma részleteit tartalmazó választ hoz létre, ha nincs definiálva egyéni kezelő.
- StatusCodePagesMiddleware: Alapértelmezés szerint létrehoz egy probléma részleteit tartalmazó választ.
-
DeveloperExceptionPageMiddleware: Probléma részleteit tartalmazó választ hoz létre a fejlesztési környezetben, amikor a kérelem HTTP-fejléce nem tartalmazza a
Acceptértéket.
Az alábbi kód úgy konfigurálja az alkalmazást, hogy probléma részleteit adja meg az összes olyan HTTP-ügyfél- és kiszolgálóhiba-válaszhoz, amely még nem rendelkezik törzstartalommal:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
A következő szakasz bemutatja, hogyan szabhatja testre a probléma részleteit tartalmazó választörzset.
A probléma részleteinek testreszabása
Az ProblemDetails automatikus létrehozása az alábbi lehetőségek bármelyikével testre szabható.
- Használja a
ProblemDetailsOptions.CustomizeProblemDetails-t - Egyéni
IProblemDetailsWriterhasználata -
Hívja a
IProblemDetailsServiceköztes szoftvert
CustomizeProblemDetails művelet
A létrehozott probléma részletei testre szabhatók a használatával CustomizeProblemDetails, és a testreszabások az automatikusan létrehozott probléma részleteire lesznek alkalmazva.
A beállításhoz ProblemDetailsOptionsa következő kód szolgálCustomizeProblemDetails:
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();
Például egy HTTP Status 400 Bad Request végpont eredménye a következő probléma részletei választ ad vissza:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Egyéni IProblemDetailsWriter
A IProblemDetailsWriter implementáció létrehozható a speciális testreszabásokhoz.
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));
}
}
Jegyzet: Egyéni IProblemDetailsWriter használata esetén a hívás IProblemDetailsWriter előtt regisztrálni kell az egyénit AddRazorPages, AddControllers, AddControllersWithViews, vagy 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();
A Middleware-ből származó probléma részletei
Az ProblemDetailsOptions és CustomizeProblemDetails használatának egyik alternatív módszere, hogy a ProblemDetails-t köztes rétegben állítjuk be. A probléma részleteire adott választ a következő hívással IProblemDetailsService.WriteAsynclehet megírni:
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();
Az előző kódban a minimális API-végpontok /divide , és /squareroot a várt egyéni hibaválaszt adja vissza a hibabemenethez.
Az API-vezérlő végpontjai az alapértelmezett hibaválaszt adják vissza a hibabemenetkor, nem pedig az egyéni problémamegoldást. A rendszer az alapértelmezett problémaválaszt adja vissza, mert az API-vezérlő a válaszstreambe írt a hibaállapotkódokkal kapcsolatos problémák részleteit, mielőtt IProblemDetailsService.WriteAsync meghívták, és a válasz nem íródik újra.
Az alábbi ValuesController visszaadja BadRequestResult, ami a válaszfolyamba ír, és így megakadályozza az egyéni probléma válaszának visszatérését.
[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));
}
}
A következő Values3Controller a ControllerBase.Problem eredményt adja vissza, így a várt egyéni probléma eredménye lesz:
[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));
}
}
Hozzon létre egy ProblemDetails adatcsomagot a kivételekhez
Fontolja meg a következő alkalmazást:
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();
Nem fejlesztési környezetekben, ha kivétel történik, a következő egy szabványos ProblemDetails-válasz , amelyet a rendszer visszaad az ügyfélnek:
{
"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"
}
A legtöbb alkalmazás esetében csak az előző kód szükséges a kivételekhez. Az alábbi szakasz azonban bemutatja, hogyan kaphat részletesebb választ a problémákra.
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését és a probléma részleteit tartalmazó válasz megírását a következővel 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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
A probléma részleteinek létrehozására másik módszer a külső NuGet-csomag, a Hellang.Middleware.ProblemDetails használata, amely a kivételek és az ügyfélhibák leképezésére használható a probléma részleteire.
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
- Az Azure App Service és az IIS ASP.NET Core hibaelhárítása
- Gyakori hibák elhárítása az Azure App Service-ben és az IIS-ben az ASP.NET Core esetén
- ASP.NET Core API-k hibáinak kezelése
Ez a cikk az ASP.NET Core-webalkalmazásokban előforduló hibák kezelésének gyakori megközelítéseit ismerteti. Lásd még : ASP.NET Core API-k hibáinak kezelése.
Fejlesztői kivételoldal
A Fejlesztői kivétel lap részletes információkat jelenít meg a nem kezelt kérelmek kivételeiről. ASP.NET Core-alkalmazások alapértelmezés szerint engedélyezik a fejlesztői kivételoldalt, ha mindkettő:
- Futtatás a fejlesztési környezetben.
- Az aktuális sablonokkal létrehozott alkalmazás, azaz a WebApplication.CreateBuilder használatával.
WebHost.CreateDefaultBuilderhasználatával készült alkalmazásoknak engedélyezniük kell a fejlesztői kivételoldalt aapp.UseDeveloperExceptionPage-ben aConfiguremeghívásával.
A fejlesztői kivételoldal a köztes szoftver folyamatának korai szakaszában fut, hogy a következő köztes szoftverben megjelenő kezeletlen kivételeket észlelhesse.
A részletes kivételadatokat nem szabad nyilvánosan megjeleníteni, amikor az alkalmazás éles környezetben fut. További információ a környezetek konfigurálásáról: ASP.NET Core futtatókörnyezetek.
A Fejlesztői kivétel lap a következő információkat tartalmazhatja a kivételről és a kérésről:
- Verem nyomkövetése
- Lekérdezési sztringparaméterek, ha vannak ilyenek
- Cookie-k, ha vannak ilyenek
- Headers
A fejlesztői kivételoldal nem garantáltan biztosít semmilyen információt. Használja a naplózást a teljes hibainformációkhoz.
Kivételkezelő lap
Ha egyéni hibakezelő lapot szeretne konfigurálni az éles környezethez, hívja meg a következőt UseExceptionHandler: . Ez a kivételkezelés köztes szoftver:
- Naplózza a kezeletlen kivételeket.
- A kérést újra végrehajtja egy másik folyamatban a megadott elérési út használatával. A rendszer nem hajtja végre újra a kérést, ha a válasz elindult. A sablon által létrehozott kód újra végrehajtja a kérést az
/Errorelérési út használatával.
Warning
Ha az alternatív csővezeték saját kivételt dob, a Kivételkezelő köztes réteg újradobja az eredeti kivételt.
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - UseExceptionHandler(IApplicationBuilder, String) A sablonokban használt túlterhelés esetén csak a kérelem útvonala módosul, és az útvonaladatok törlődnek. A kérelemadatok, például a fejlécek, a metódusok és az elemek mind újra felhasználhatók as-is.
- A hatókörön belüli szolgáltatások változatlanok maradnak.
Az alábbi példában a UseExceptionHandler hozzáadja a kivételkezelő middleware-t a fejlesztési környezeteken kívüli környezetekben.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
A Razor Lapok alkalmazássablon egy Hibalapot (.cshtml) és PageModel osztályt (ErrorModel) biztosít a Lapok mappában. MVC-alkalmazások esetén a projektsablon tartalmaz egy Error műveletmetódust és egy hibanézetet a Home vezérlőhöz.
A köztes szoftver kivételkezelése újra végrehajtja a kérést az eredeti HTTP-módszerrel. Ha egy hibakezelő végpont a HTTP-metódusok egy meghatározott halmazára korlátozódik, az csak az adott HTTP-metódusokhoz fut. Az attribútumot használó [HttpGet] MVC-vezérlőművelet például csak GET-kérelmek esetén fut. Annak érdekében, hogy minden kérés elérje az egyéni hibakezelő lapot, ne korlátozza azokat a HTTP-metódusok meghatározott készletére.
A kivételek eltérő kezelése az eredeti HTTP-módszer alapján:
- A Razor Pages esetében hozzon létre több kezelő metódusokat. Például a
OnGeta GET-kivételek kezelésére, míg aOnPosta POST-kivételek kezelésére használható. - MVC esetén http-igeattribútumokat alkalmazhat több műveletre. Például a
[HttpGet]a GET-kivételek kezelésére, míg a[HttpPost]a POST-kivételek kezelésére használható.
Ha engedélyezni szeretné, hogy a hitelesítés nélküli felhasználók megtekinthessék az egyéni hibakezelő lapot, győződjön meg arról, hogy támogatja a névtelen hozzáférést.
A kivétel elérése
Használja a IExceptionHandlerPathFeature elemet a kivétel és az eredeti kérési útvonal elérésére egy hibakezelőben. Az alábbi példa IExceptionHandlerPathFeature a kidobott kivételről nyújt további információt:
[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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
Kivételkezelő lambda
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését a válasz visszaadása előtt.
A következő kód egy lambdát használ a kivételkezeléshez:
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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
IExceptionHandler
IExceptionHandler egy olyan felület, amely visszahívást biztosít a fejlesztőnek egy központi helyen lévő ismert kivételek kezelésére.
IExceptionHandler az implementációk regisztrálásához a IServiceCollection.AddExceptionHandler<T> használják: [IServiceCollection.AddExceptionHandler<T>]. Az IExceptionHandler példány élettartama singleton. Több implementáció is hozzáadható, és a rendszer a regisztrált sorrendben hívja meg őket.
Ha egy kivételkezelő kezel egy kérést, true adhat vissza a feldolgozás leállításához. Ha egy kivételt egyetlen kivételkezelő sem kezel, akkor a vezérlés visszaesik a köztes szoftver alapértelmezett viselkedésére és beállításaira. Különböző metrikákat és naplókat bocsát ki a rendszer a kezelt és kezeletlen kivételek esetén.
Az alábbi példa egy implementációt IExceptionHandler mutat be:
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);
}
}
}
Az alábbi példa bemutatja, hogyan regisztrálhat implementációt IExceptionHandler függőséginjektáláshoz:
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
Ha az előző kód a fejlesztési környezetben fut:
- A
CustomExceptionHandlerelőször meghívódik a kivétel kezelésére. - A kivétel naplózása után a
TryHandleExceptionmetódus visszatérfalse, így megjelenik a fejlesztői kivétellap.
Más környezetekben:
- A
CustomExceptionHandlerelőször meghívódik a kivétel kezelésére. - A kivétel naplózása után a
TryHandleExceptionmetódus visszatér, így megjelenikfalseaz/Erroroldal .
UseStatusCodePages
Alapértelmezés szerint egy ASP.NET Core-alkalmazás nem biztosít állapotkódlapot a HTTP-hibaállapot-kódokhoz, például 404 – Nem található. Amikor az alkalmazás beállít egy HTTP 400-599 hibaállapot-kódot, amely nem tartalmaz törzset, az állapotkódot és egy üres választörzset ad vissza. Ha engedélyezni szeretné az alapértelmezett csak szöveges kezelőket a gyakori hibaállapot-kódokhoz, hívja meg UseStatusCodePages a Program.cs-ben:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Hívás UseStatusCodePages a köztes szoftverrel kapcsolatos kérések kezelése előtt. Hívja például a UseStatusCodePages parancsot a statikus fájlok köztes rétege és az Endpoints Middleware előtt.
Ha UseStatusCodePages nincs használatban, a végpont nélküli URL-címre való navigálás egy böngészőfüggő hibaüzenetet ad vissza, amely jelzi, hogy a végpont nem található. Amikor UseStatusCodePages a rendszer meghívja, a böngésző a következő választ adja vissza:
Status Code: 404; Not Found
UseStatusCodePages általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
Note
Az állapotkódlapok köztes szoftverei nem észlelnek kivételeket. Egyéni hibakezelő lap megadásához használja a kivételkezelő lapot.
UseStatusCodePages formátum sztring alkalmazásával
A válasz tartalomtípusának és szövegének testreszabásához használja azt a UseStatusCodePages túlterhelést, amely tartalomtípust és formázási sztringet vesz fel.
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}");
Az előző kódban a {0} egy helyőrző a hibakód számára.
UseStatusCodePages a formátumsztringet általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePages a lambda kifejezéssel
Az egyéni hibakezelési és válaszírási kód megadásához használja az UseStatusCodePages azon túlterhelését, amely elfogad egy lambda kifejezést:
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}");
});
A lambdát általában nem használják termelési környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePagesWithRedirects
A UseStatusCodePagesWithRedirects bővítmény metódusa:
- 302 – Talált állapotkódot küld az ügyfélnek.
- Átirányítja az ügyfelet az URL-sablonban megadott hibakezelési végpontra. A hibakezelő végpont általában hibainformációkat jelenít meg, és HTTP 200-et ad vissza.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Az URL-sablon tartalmazhat helyőrzőt {0} az állapotkódhoz, ahogyan az az előző kódban is látható. Ha az URL-sablon ~ (tilde) jellel kezdődik ~, akkor az ~ helyébe az alkalmazás PathBase kerül. Amikor végpontot ad meg az alkalmazásban, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják az alkalmazás esetében:
- Az ügyfelet egy másik végpontra kell átirányítani, általában olyan esetekben, amikor egy másik alkalmazás feldolgozza a hibát. Webalkalmazások esetén az ügyfél böngészőcímsávja az átirányított végpontot tükrözi.
- Ne őrizze meg és ne adja vissza az eredeti állapotkódot az első átirányítási válasznál.
UseStatusCodePagesWithReExecute
A UseStatusCodePagesWithReExecute bővítmény metódusa:
- A válasz törzsét úgy hozza létre, hogy egy másik elérési út használatával újra végrehajtja a kérelemfolyamatot.
- Nem módosítja az állapotkódot a folyamat ismételt végrehajtása előtt vagy után.
Az új folyamat végrehajtása megváltoztathatja a válasz állapotkódját, mivel az új folyamat teljes mértékben szabályozza az állapotkódot. Ha az új folyamat nem módosítja az állapotkódot, a rendszer elküldi az eredeti állapotkódot az ügyfélnek.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Ha az alkalmazásban egy végpont van megadva, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják, amikor az alkalmazásnak a következőt kell használnia:
- A kérés feldolgozása egy másik végpontra való átirányítás nélkül. Webalkalmazások esetén az ügyfél böngészőcímsávja az eredetileg kért végpontot tükrözi.
- Őrizze meg és adja vissza az eredeti állapotkódot a válaszsal együtt.
Az URL-sablonnak kezdődnie kell, / és tartalmaznia kell egy helyőrzőt {0} az állapotkódhoz. Ha az állapotkódot lekérdezési sztring paraméterként szeretné átadni, adjon át egy második argumentumot a következőbe UseStatusCodePagesWithReExecute: Például:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
A hibát feldolgozó végpont lekérheti a hibát létrehozó eredeti URL-címet, ahogyan az az alábbi példában látható:
[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}";
}
}
}
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - A hatókörön belüli szolgáltatások változatlanok maradnak.
Állapotkódlapok letiltása
MVC-vezérlő vagy műveleti metódus állapotkódlapjainak letiltásához használja a [SkipStatusCodePages] attribútumot.
Ha le szeretné tiltani az állapotkódlapokat a Razor Pages-kezelő metódusban vagy egy MVC-vezérlőben megadott kérésekhez, használja a következőt IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kivételkezelési kód
A kivételkezelő lapok kódjai kivételeket is okozhatnak. A gyártási hibaoldalakat alaposan tesztelni kell, és fokozottan ügyelni kell arra, hogy elkerüljük a sajátjaik által okozott kivételeket.
Válaszfejlécek
A válasz fejléceinek elküldése után:
- Az alkalmazás nem tudja módosítani a válasz állapotkódját.
- A kivételoldalak vagy -kezelők nem futtathatók. A választ be kell fejezni, vagy megszakadt a kapcsolat.
Kiszolgálói kivételkezelés
Az alkalmazások kivételkezelési logikája mellett a HTTP-kiszolgáló implementációja is képes kezelni néhány kivételt. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése előtt, a kiszolgáló választörzs nélkül küld 500 - Internal Server Error választ. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése után, a kiszolgáló bezárja a kapcsolatot. Az alkalmazás által nem kezelt kérelmeket a kiszolgáló kezeli. Minden kivételt, amely akkor fordul elő, amikor a kiszolgáló kezeli a kérést, a kiszolgáló kivételkezelése kezeli. Az alkalmazás egyéni hibaoldalai, a köztes szoftver kivételkezelése és a szűrők nem befolyásolják ezt a viselkedést.
Indítási kivétel kezelése
Csak az üzemeltetési réteg képes kezelni az alkalmazás indításakor előforduló kivételeket. A gazdagép konfigurálható az indítási hibák és a részletes hibák rögzítésére.
A fogadó réteg csak akkor jeleníthet meg hibalapot egy észlelt indítási hiba esetén, ha a hiba a gazdacím/port kötése után következik be. Ha a kötés sikertelen:
- Az üzemeltetési réteg kritikus kivételt naplóz.
- A dotnet-folyamat összeomlik.
- HTTP-kiszolgáló Kestrel állapotában nem jelenik meg hibaoldal.
Ha IIS-en (vagy Azure App Service-en) vagy IIS Expressen fut, az ASP.NET core modul502.5-ös folyamathibát ad vissza, ha a folyamat nem indítható el. További információ: ASP.NET Core hibaelhárítása az Azure App Service-ben és az IIS-ben.
Adatbázis hibaoldala
Az adatbázis fejlesztői lapjának kivételszűrője AddDatabaseDeveloperPageExceptionFilter rögzíti az adatbázissal kapcsolatos kivételeket, amelyek az Entity Framework Core migrálásával oldhatók meg. Ha ezek a kivételek előfordulnak, a rendszer HTML-választ hoz létre a probléma megoldásához szükséges lehetséges műveletek részleteivel. Ez a lap csak a fejlesztési környezetben engedélyezett. A következő kód hozzáadja az Adatbázis fejlesztői oldal kivételszűrőjét:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Kivételszűrők
Az MVC-alkalmazásokban a kivételszűrők globálisan, vezérlőnként vagy műveletenként konfigurálhatók. A Razor Pages-alkalmazásokban globálisan vagy oldalmodellenként konfigurálhatók. Ezek a szűrők kezelik a vezérlőművelet vagy egy másik szűrő végrehajtása során előforduló nem kezelt kivételeket. További információ: Szűrők a ASP.NET Core-ban.
A kivételszűrők hasznosak az MVC-műveletekben előforduló kivételek csapdába ejtéséhez, de nem olyan rugalmasak, mint a beépített kivételkezelő köztes szoftver, UseExceptionHandler. Javasoljuk, hogy használja UseExceptionHandler, kivéve, ha a hibakezelést a választott MVC-művelet alapján eltérő módon kell elvégeznie.
Modellállapot-hibák
A modellállapot-hibák kezelésével kapcsolatos információkért tekintse meg a modellkötést és a modellérvényesítést ismertető témakört.
Probléma részletei
A probléma részletei nem az egyetlen válaszformátum a HTTP API-hibák leírásához, azonban gyakran használják őket a HTTP API-k hibáinak jelentésére.
A probléma részletei szolgáltatás implementálja a felületet, amely támogatja a IProblemDetailsService probléma részleteinek létrehozását a ASP.NET Core-ban. A AddProblemDetails(IServiceCollection) bővítménymetódus a IServiceCollection regisztrálja az alapértelmezett IProblemDetailsService implementációt.
A ASP.NET Core-alkalmazásokban a következő köztes szoftver generálja a probléma részleteit HTTP-válaszok meghívásakorAddProblemDetails, kivéve, ha a Accept kérelem HTTP-fejléce nem tartalmazza a regisztrált IProblemDetailsWriter (alapértelmezett) által támogatott tartalomtípusokat: application/json
- ExceptionHandlerMiddleware: Probléma részleteit tartalmazó választ hoz létre, ha nincs definiálva egyéni kezelő.
- StatusCodePagesMiddleware: Alapértelmezés szerint létrehoz egy probléma részleteit tartalmazó választ.
-
DeveloperExceptionPageMiddleware: Probléma részleteit tartalmazó választ hoz létre a fejlesztési környezetben, amikor a kérelem HTTP-fejléce nem tartalmazza a
Acceptértéket.
Az alábbi kód úgy konfigurálja az alkalmazást, hogy probléma részleteit adja meg az összes olyan HTTP-ügyfél- és kiszolgálóhiba-válaszhoz, amely még nem rendelkezik törzstartalommal:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
A következő szakasz bemutatja, hogyan szabhatja testre a probléma részleteit tartalmazó választörzset.
A probléma részleteinek testreszabása
Az ProblemDetails automatikus létrehozása az alábbi lehetőségek bármelyikével testre szabható.
- Használja a
ProblemDetailsOptions.CustomizeProblemDetails-t - Egyéni
IProblemDetailsWriterhasználata -
Hívja a
IProblemDetailsServiceköztes szoftvert
CustomizeProblemDetails művelet
A létrehozott probléma részletei testre szabhatók a használatával CustomizeProblemDetails, és a testreszabások az automatikusan létrehozott probléma részleteire lesznek alkalmazva.
A beállításhoz ProblemDetailsOptionsa következő kód szolgálCustomizeProblemDetails:
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();
Például egy HTTP Status 400 Bad Request végpont eredménye a következő probléma részletei választ ad vissza:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Egyéni IProblemDetailsWriter
A IProblemDetailsWriter implementáció létrehozható a speciális testreszabásokhoz.
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));
}
}
Jegyzet: Egyéni IProblemDetailsWriter használata esetén a hívás IProblemDetailsWriter előtt regisztrálni kell az egyénit AddRazorPages, AddControllers, AddControllersWithViews, vagy 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();
A Middleware-ből származó probléma részletei
Az ProblemDetailsOptions és CustomizeProblemDetails használatának egyik alternatív módszere, hogy a ProblemDetails-t köztes rétegben állítjuk be. A probléma részleteire adott választ a következő hívással IProblemDetailsService.WriteAsynclehet megírni:
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();
Az előző kódban a minimális API-végpontok /divide , és /squareroot a várt egyéni hibaválaszt adja vissza a hibabemenethez.
Az API-vezérlő végpontjai az alapértelmezett hibaválaszt adják vissza a hibabemenetkor, nem pedig az egyéni problémamegoldást. A rendszer az alapértelmezett problémaválaszt adja vissza, mert az API-vezérlő a válaszstreambe írt a hibaállapotkódokkal kapcsolatos problémák részleteit, mielőtt IProblemDetailsService.WriteAsync meghívták, és a válasz nem íródik újra.
Az alábbi ValuesController visszaadja BadRequestResult, ami a válaszfolyamba ír, és így megakadályozza az egyéni probléma válaszának visszatérését.
[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));
}
}
A következő Values3Controller a ControllerBase.Problem eredményt adja vissza, így a várt egyéni probléma eredménye lesz:
[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));
}
}
Hozzon létre egy ProblemDetails adatcsomagot a kivételekhez
Fontolja meg a következő alkalmazást:
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();
Nem fejlesztési környezetekben, ha kivétel történik, a következő egy szabványos ProblemDetails-válasz , amelyet a rendszer visszaad az ügyfélnek:
{
"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"
}
A legtöbb alkalmazás esetében csak az előző kód szükséges a kivételekhez. Az alábbi szakasz azonban bemutatja, hogyan kaphat részletesebb választ a problémákra.
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését és a probléma részleteit tartalmazó válasz megírását a következővel 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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
A probléma részleteinek létrehozására másik módszer a külső NuGet-csomag, a Hellang.Middleware.ProblemDetails használata, amely a kivételek és az ügyfélhibák leképezésére használható a probléma részleteire.
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
- Az Azure App Service és az IIS ASP.NET Core hibaelhárítása
- Gyakori hibák elhárítása az Azure App Service-ben és az IIS-ben az ASP.NET Core esetén
- ASP.NET Core API-k hibáinak kezelése
- A ASP.NET Core API-k hibáinak kezelése.
Ez a cikk az ASP.NET Core-webalkalmazásokban előforduló hibák kezelésének gyakori megközelítéseit ismerteti. Lásd még : ASP.NET Core API-k hibáinak kezelése.
Fejlesztői kivételoldal
A Fejlesztői kivétel lap részletes információkat jelenít meg a nem kezelt kérelmek kivételeiről. ASP.NET Core-alkalmazások alapértelmezés szerint engedélyezik a fejlesztői kivételoldalt, ha mindkettő:
- Futtatás a fejlesztési környezetben.
- Az aktuális sablonokkal létrehozott alkalmazás, azaz a WebApplication.CreateBuilder használatával.
WebHost.CreateDefaultBuilderhasználatával készült alkalmazásoknak engedélyezniük kell a fejlesztői kivételoldalt aapp.UseDeveloperExceptionPage-ben aConfiguremeghívásával.
A fejlesztői kivételoldal a köztes szoftver folyamatának korai szakaszában fut, hogy a következő köztes szoftverben megjelenő kezeletlen kivételeket észlelhesse.
A részletes kivételadatokat nem szabad nyilvánosan megjeleníteni, amikor az alkalmazás éles környezetben fut. További információ a környezetek konfigurálásáról: ASP.NET Core futtatókörnyezetek.
A Fejlesztői kivétel lap a következő információkat tartalmazhatja a kivételről és a kérésről:
- Verem nyomkövetése
- Lekérdezési sztringparaméterek, ha vannak ilyenek
- Cookie-k, ha vannak ilyenek
- Headers
A fejlesztői kivételoldal nem garantáltan biztosít semmilyen információt. Használja a naplózást a teljes hibainformációkhoz.
Kivételkezelő lap
Ha egyéni hibakezelő lapot szeretne konfigurálni az éles környezethez, hívja meg a következőt UseExceptionHandler: . Ez a kivételkezelés köztes szoftver:
- Naplózza a kezeletlen kivételeket.
- A kérést újra végrehajtja egy másik folyamatban a megadott elérési út használatával. A rendszer nem hajtja végre újra a kérést, ha a válasz elindult. A sablon által létrehozott kód újra végrehajtja a kérést az
/Errorelérési út használatával.
Warning
Ha az alternatív csővezeték saját kivételt dob, a Kivételkezelő köztes réteg újradobja az eredeti kivételt.
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - UseExceptionHandler(IApplicationBuilder, String) A sablonokban használt túlterhelés esetén csak a kérelem útvonala módosul, és az útvonaladatok törlődnek. A kérelemadatok, például a fejlécek, a metódusok és az elemek mind újra felhasználhatók as-is.
- A hatókörön belüli szolgáltatások változatlanok maradnak.
Az alábbi példában a UseExceptionHandler hozzáadja a kivételkezelő middleware-t a fejlesztési környezeteken kívüli környezetekben.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
A Razor Lapok alkalmazássablon egy Hibalapot (.cshtml) és PageModel osztályt (ErrorModel) biztosít a Lapok mappában. MVC-alkalmazások esetén a projektsablon tartalmaz egy Error műveletmetódust és egy hibanézetet a Home vezérlőhöz.
A köztes szoftver kivételkezelése újra végrehajtja a kérést az eredeti HTTP-módszerrel. Ha egy hibakezelő végpont a HTTP-metódusok egy meghatározott halmazára korlátozódik, az csak az adott HTTP-metódusokhoz fut. Az attribútumot használó [HttpGet] MVC-vezérlőművelet például csak GET-kérelmek esetén fut. Annak érdekében, hogy minden kérés elérje az egyéni hibakezelő lapot, ne korlátozza azokat a HTTP-metódusok meghatározott készletére.
A kivételek eltérő kezelése az eredeti HTTP-módszer alapján:
- A Razor Pages esetében hozzon létre több kezelő metódusokat. Például a
OnGeta GET-kivételek kezelésére, míg aOnPosta POST-kivételek kezelésére használható. - MVC esetén http-igeattribútumokat alkalmazhat több műveletre. Például a
[HttpGet]a GET-kivételek kezelésére, míg a[HttpPost]a POST-kivételek kezelésére használható.
Ha engedélyezni szeretné, hogy a hitelesítés nélküli felhasználók megtekinthessék az egyéni hibakezelő lapot, győződjön meg arról, hogy támogatja a névtelen hozzáférést.
A kivétel elérése
Használja a IExceptionHandlerPathFeature elemet a kivétel és az eredeti kérési útvonal elérésére egy hibakezelőben. Az alábbi példa IExceptionHandlerPathFeature a kidobott kivételről nyújt további információt:
[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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
Kivételkezelő lambda
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését a válasz visszaadása előtt.
A következő kód egy lambdát használ a kivételkezeléshez:
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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
UseStatusCodePages
Alapértelmezés szerint egy ASP.NET Core-alkalmazás nem biztosít állapotkódlapot a HTTP-hibaállapot-kódokhoz, például 404 – Nem található. Amikor az alkalmazás beállít egy HTTP 400-599 hibaállapot-kódot, amely nem tartalmaz törzset, az állapotkódot és egy üres választörzset ad vissza. Ha engedélyezni szeretné az alapértelmezett csak szöveges kezelőket a gyakori hibaállapot-kódokhoz, hívja meg UseStatusCodePages a Program.cs-ben:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Hívás UseStatusCodePages a köztes szoftverrel kapcsolatos kérések kezelése előtt. Hívja például a UseStatusCodePages parancsot a statikus fájlok köztes rétege és az Endpoints Middleware előtt.
Ha UseStatusCodePages nincs használatban, a végpont nélküli URL-címre való navigálás egy böngészőfüggő hibaüzenetet ad vissza, amely jelzi, hogy a végpont nem található. Amikor UseStatusCodePages a rendszer meghívja, a böngésző a következő választ adja vissza:
Status Code: 404; Not Found
UseStatusCodePages általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
Note
Az állapotkódlapok köztes szoftverei nem észlelnek kivételeket. Egyéni hibakezelő lap megadásához használja a kivételkezelő lapot.
UseStatusCodePages formátum sztring alkalmazásával
A válasz tartalomtípusának és szövegének testreszabásához használja azt a UseStatusCodePages túlterhelést, amely tartalomtípust és formázási sztringet vesz fel.
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}");
Az előző kódban a {0} egy helyőrző a hibakód számára.
UseStatusCodePages a formátumsztringet általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePages a lambda kifejezéssel
Az egyéni hibakezelési és válaszírási kód megadásához használja az UseStatusCodePages azon túlterhelését, amely elfogad egy lambda kifejezést:
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}");
});
A lambdát általában nem használják termelési környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePagesWithRedirects
A UseStatusCodePagesWithRedirects bővítmény metódusa:
- 302 – Talált állapotkódot küld az ügyfélnek.
- Átirányítja az ügyfelet az URL-sablonban megadott hibakezelési végpontra. A hibakezelő végpont általában hibainformációkat jelenít meg, és HTTP 200-et ad vissza.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Az URL-sablon tartalmazhat helyőrzőt {0} az állapotkódhoz, ahogyan az az előző kódban is látható. Ha az URL-sablon ~ (tilde) jellel kezdődik ~, akkor az ~ helyébe az alkalmazás PathBase kerül. Amikor végpontot ad meg az alkalmazásban, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják az alkalmazás esetében:
- Az ügyfelet egy másik végpontra kell átirányítani, általában olyan esetekben, amikor egy másik alkalmazás feldolgozza a hibát. Webalkalmazások esetén az ügyfél böngészőcímsávja az átirányított végpontot tükrözi.
- Ne őrizze meg és ne adja vissza az eredeti állapotkódot az első átirányítási válasznál.
UseStatusCodePagesWithReExecute
A UseStatusCodePagesWithReExecute bővítmény metódusa:
- A válasz törzsét úgy hozza létre, hogy egy másik elérési út használatával újra végrehajtja a kérelemfolyamatot.
- Nem módosítja az állapotkódot a folyamat ismételt végrehajtása előtt vagy után.
Az új folyamat végrehajtása megváltoztathatja a válasz állapotkódját, mivel az új folyamat teljes mértékben szabályozza az állapotkódot. Ha az új folyamat nem módosítja az állapotkódot, a rendszer elküldi az eredeti állapotkódot az ügyfélnek.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Ha az alkalmazásban egy végpont van megadva, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják, amikor az alkalmazásnak a következőt kell használnia:
- A kérés feldolgozása egy másik végpontra való átirányítás nélkül. Webalkalmazások esetén az ügyfél böngészőcímsávja az eredetileg kért végpontot tükrözi.
- Őrizze meg és adja vissza az eredeti állapotkódot a válaszsal együtt.
Az URL-sablonnak kezdődnie kell, / és tartalmaznia kell egy helyőrzőt {0} az állapotkódhoz. Ha az állapotkódot lekérdezési sztring paraméterként szeretné átadni, adjon át egy második argumentumot a következőbe UseStatusCodePagesWithReExecute: Például:
var app = builder.Build();
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
A hibát feldolgozó végpont lekérheti a hibát létrehozó eredeti URL-címet, ahogyan az az alábbi példában látható:
[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}";
}
}
}
Mivel ez a köztes szoftver újra tudja futtatni a kérési folyamatot:
- A köztes rétegeknek kezelniük kell a reentranciát ugyanazzal a kéréssel. Ez általában azt jelenti, hogy a hívás
_nextután megtisztítják az állapotukat, vagy a feldolgozásukatHttpContextgyorsítótárazzák, hogy elkerüljék az újbóli elvégzést. A kérelem törzsének kezelésekor ez az eredmények pufferelését vagy gyorsítótárazását jelenti, ahogyan azt az Űrlapolvasó is teszi. - A hatókörön belüli szolgáltatások változatlanok maradnak.
Állapotkódlapok letiltása
MVC-vezérlő vagy műveleti metódus állapotkódlapjainak letiltásához használja a [SkipStatusCodePages] attribútumot.
Ha le szeretné tiltani az állapotkódlapokat a Razor Pages-kezelő metódusban vagy egy MVC-vezérlőben megadott kérésekhez, használja a következőt IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kivételkezelési kód
A kivételkezelő lapok kódjai kivételeket is okozhatnak. A gyártási hibaoldalakat alaposan tesztelni kell, és fokozottan ügyelni kell arra, hogy elkerüljük a sajátjaik által okozott kivételeket.
Válaszfejlécek
A válasz fejléceinek elküldése után:
- Az alkalmazás nem tudja módosítani a válasz állapotkódját.
- A kivételoldalak vagy -kezelők nem futtathatók. A választ be kell fejezni, vagy megszakadt a kapcsolat.
Kiszolgálói kivételkezelés
Az alkalmazások kivételkezelési logikája mellett a HTTP-kiszolgáló implementációja is képes kezelni néhány kivételt. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése előtt, a kiszolgáló választörzs nélkül küld 500 - Internal Server Error választ. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése után, a kiszolgáló bezárja a kapcsolatot. Az alkalmazás által nem kezelt kérelmeket a kiszolgáló kezeli. Minden kivételt, amely akkor fordul elő, amikor a kiszolgáló kezeli a kérést, a kiszolgáló kivételkezelése kezeli. Az alkalmazás egyéni hibaoldalai, a köztes szoftver kivételkezelése és a szűrők nem befolyásolják ezt a viselkedést.
Indítási kivétel kezelése
Csak az üzemeltetési réteg képes kezelni az alkalmazás indításakor előforduló kivételeket. A gazdagép konfigurálható az indítási hibák és a részletes hibák rögzítésére.
A fogadó réteg csak akkor jeleníthet meg hibalapot egy észlelt indítási hiba esetén, ha a hiba a gazdacím/port kötése után következik be. Ha a kötés sikertelen:
- Az üzemeltetési réteg kritikus kivételt naplóz.
- A dotnet-folyamat összeomlik.
- HTTP-kiszolgáló Kestrel állapotában nem jelenik meg hibaoldal.
Ha IIS-en (vagy Azure App Service-en) vagy IIS Expressen fut, az ASP.NET core modul502.5-ös folyamathibát ad vissza, ha a folyamat nem indítható el. További információ: ASP.NET Core hibaelhárítása az Azure App Service-ben és az IIS-ben.
Adatbázis hibaoldala
Az adatbázis fejlesztői lapjának kivételszűrője AddDatabaseDeveloperPageExceptionFilter rögzíti az adatbázissal kapcsolatos kivételeket, amelyek az Entity Framework Core migrálásával oldhatók meg. Ha ezek a kivételek előfordulnak, a rendszer HTML-választ hoz létre a probléma megoldásához szükséges lehetséges műveletek részleteivel. Ez a lap csak a fejlesztési környezetben engedélyezett. A következő kód hozzáadja az Adatbázis fejlesztői oldal kivételszűrőjét:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Kivételszűrők
Az MVC-alkalmazásokban a kivételszűrők globálisan, vezérlőnként vagy műveletenként konfigurálhatók. A Razor Pages-alkalmazásokban globálisan vagy oldalmodellenként konfigurálhatók. Ezek a szűrők kezelik a vezérlőművelet vagy egy másik szűrő végrehajtása során előforduló nem kezelt kivételeket. További információ: Szűrők a ASP.NET Core-ban.
A kivételszűrők hasznosak az MVC-műveletekben előforduló kivételek csapdába ejtéséhez, de nem olyan rugalmasak, mint a beépített kivételkezelő köztes szoftver, UseExceptionHandler. Javasoljuk, hogy használja UseExceptionHandler, kivéve, ha a hibakezelést a választott MVC-művelet alapján eltérő módon kell elvégeznie.
Modellállapot-hibák
A modellállapot-hibák kezelésével kapcsolatos információkért tekintse meg a modellkötést és a modellérvényesítést ismertető témakört.
Probléma részletei
A probléma részletei nem az egyetlen válaszformátum a HTTP API-hibák leírásához, azonban gyakran használják őket a HTTP API-k hibáinak jelentésére.
A probléma részletei szolgáltatás implementálja a felületet, amely támogatja a IProblemDetailsService probléma részleteinek létrehozását a ASP.NET Core-ban. A AddProblemDetails(IServiceCollection) bővítménymetódus a IServiceCollection regisztrálja az alapértelmezett IProblemDetailsService implementációt.
A ASP.NET Core-alkalmazásokban a következő köztes szoftver generálja a probléma részleteit HTTP-válaszok meghívásakorAddProblemDetails, kivéve, ha a Accept kérelem HTTP-fejléce nem tartalmazza a regisztrált IProblemDetailsWriter (alapértelmezett) által támogatott tartalomtípusokat: application/json
- ExceptionHandlerMiddleware: Probléma részleteit tartalmazó választ hoz létre, ha nincs definiálva egyéni kezelő.
- StatusCodePagesMiddleware: Alapértelmezés szerint létrehoz egy probléma részleteit tartalmazó választ.
-
DeveloperExceptionPageMiddleware: Probléma részleteit tartalmazó választ hoz létre a fejlesztési környezetben, amikor a kérelem HTTP-fejléce nem tartalmazza a
Acceptértéket.
Az alábbi kód úgy konfigurálja az alkalmazást, hogy probléma részleteit adja meg az összes olyan HTTP-ügyfél- és kiszolgálóhiba-válaszhoz, amely még nem rendelkezik törzstartalommal:
builder.Services.AddProblemDetails();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler();
app.UseHsts();
}
app.UseStatusCodePages();
A következő szakasz bemutatja, hogyan szabhatja testre a probléma részleteit tartalmazó választörzset.
A probléma részleteinek testreszabása
Az ProblemDetails automatikus létrehozása az alábbi lehetőségek bármelyikével testre szabható.
- Használja a
ProblemDetailsOptions.CustomizeProblemDetails-t - Egyéni
IProblemDetailsWriterhasználata -
Hívja a
IProblemDetailsServiceköztes szoftvert
CustomizeProblemDetails művelet
A létrehozott probléma részletei testre szabhatók a használatával CustomizeProblemDetails, és a testreszabások az automatikusan létrehozott probléma részleteire lesznek alkalmazva.
A beállításhoz ProblemDetailsOptionsa következő kód szolgálCustomizeProblemDetails:
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();
Például egy HTTP Status 400 Bad Request végpont eredménye a következő probléma részletei választ ad vissza:
{
"type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
"title": "Bad Request",
"status": 400,
"nodeId": "my-machine-name"
}
Egyéni IProblemDetailsWriter
A IProblemDetailsWriter implementáció létrehozható a speciális testreszabásokhoz.
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));
}
}
Jegyzet: Egyéni IProblemDetailsWriter használata esetén a hívás IProblemDetailsWriter előtt regisztrálni kell az egyénit AddRazorPages, AddControllers, AddControllersWithViews, vagy 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();
A Middleware-ből származó probléma részletei
Az ProblemDetailsOptions és CustomizeProblemDetails használatának egyik alternatív módszere, hogy a ProblemDetails-t köztes rétegben állítjuk be. A probléma részleteire adott választ a következő hívással IProblemDetailsService.WriteAsynclehet megírni:
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();
Az előző kódban a minimális API-végpontok /divide , és /squareroot a várt egyéni hibaválaszt adja vissza a hibabemenethez.
Az API-vezérlő végpontjai az alapértelmezett hibaválaszt adják vissza a hibabemenetkor, nem pedig az egyéni problémamegoldást. A rendszer az alapértelmezett problémaválaszt adja vissza, mert az API-vezérlő a válaszstreambe írt a hibaállapotkódokkal kapcsolatos problémák részleteit, mielőtt IProblemDetailsService.WriteAsync meghívták, és a válasz nem íródik újra.
Az alábbi ValuesController visszaadja BadRequestResult, ami a válaszfolyamba ír, és így megakadályozza az egyéni probléma válaszának visszatérését.
[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));
}
}
A következő Values3Controller a ControllerBase.Problem eredményt adja vissza, így a várt egyéni probléma eredménye lesz:
[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));
}
}
Hozzon létre egy ProblemDetails adatcsomagot a kivételekhez
Fontolja meg a következő alkalmazást:
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();
Nem fejlesztési környezetekben, ha kivétel történik, a következő egy szabványos ProblemDetails-válasz , amelyet a rendszer visszaad az ügyfélnek:
{
"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"
}
A legtöbb alkalmazás esetében csak az előző kód szükséges a kivételekhez. Az alábbi szakasz azonban bemutatja, hogyan kaphat részletesebb választ a problémákra.
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését és a probléma részleteit tartalmazó válasz megírását a következővel 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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
A probléma részleteinek létrehozására másik módszer a külső NuGet-csomag, a Hellang.Middleware.ProblemDetails használata, amely a kivételek és az ügyfélhibák leképezésére használható a probléma részleteire.
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
- Az Azure App Service és az IIS ASP.NET Core hibaelhárítása
- Gyakori hibák elhárítása az Azure App Service-ben és az IIS-ben az ASP.NET Core esetén
Ez a cikk az ASP.NET Core-webalkalmazásokban előforduló hibák kezelésének gyakori megközelítéseit ismerteti. Lásd: A webes API-khoz készült ASP.NET Core API-k hibáinak kezelése .
Fejlesztői kivételoldal
A Fejlesztői kivétel lap részletes információkat jelenít meg a nem kezelt kérelmek kivételeiről. ASP.NET Core-alkalmazások alapértelmezés szerint engedélyezik a fejlesztői kivételoldalt, ha mindkettő:
- Futtatás a fejlesztési környezetben.
- Az aktuális sablonokkal létrehozott alkalmazás, azaz a WebApplication.CreateBuilder használatával.
WebHost.CreateDefaultBuilderhasználatával készült alkalmazásoknak engedélyezniük kell a fejlesztői kivételoldalt aapp.UseDeveloperExceptionPage-ben aConfiguremeghívásával.
A fejlesztői kivételoldal a köztes szoftver folyamatának korai szakaszában fut, hogy a következő köztes szoftverben megjelenő kezeletlen kivételeket észlelhesse.
A részletes kivételadatokat nem szabad nyilvánosan megjeleníteni, amikor az alkalmazás éles környezetben fut. További információ a környezetek konfigurálásáról: ASP.NET Core futtatókörnyezetek.
A Fejlesztői kivétel lap a következő információkat tartalmazhatja a kivételről és a kérésről:
- Verem nyomkövetése
- Lekérdezési sztringparaméterek, ha vannak ilyenek
- Cookie-k, ha vannak ilyenek
- Headers
A fejlesztői kivételoldal nem garantáltan biztosít semmilyen információt. Használja a naplózást a teljes hibainformációkhoz.
Kivételkezelő lap
Ha egyéni hibakezelő lapot szeretne konfigurálni az éles környezethez, hívja meg a következőt UseExceptionHandler: . Ez a kivételkezelés köztes szoftver:
- Naplózza a kezeletlen kivételeket.
- A kérést újra végrehajtja egy másik folyamatban a megadott elérési út használatával. A rendszer nem hajtja végre újra a kérést, ha a válasz elindult. A sablon által létrehozott kód újra végrehajtja a kérést az
/Errorelérési út használatával.
Warning
Ha az alternatív csővezeték saját kivételt dob, a Kivételkezelő köztes réteg újradobja az eredeti kivételt.
Az alábbi példában a UseExceptionHandler hozzáadja a kivételkezelő middleware-t a fejlesztési környezeteken kívüli környezetekben.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
A Razor Lapok alkalmazássablon egy Hibalapot (.cshtml) és PageModel osztályt (ErrorModel) biztosít a Lapok mappában. MVC-alkalmazások esetén a projektsablon tartalmaz egy Error műveletmetódust és egy hibanézetet a Home vezérlőhöz.
A köztes szoftver kivételkezelése újra végrehajtja a kérést az eredeti HTTP-módszerrel. Ha egy hibakezelő végpont a HTTP-metódusok egy meghatározott halmazára korlátozódik, az csak az adott HTTP-metódusokhoz fut. Az attribútumot használó [HttpGet] MVC-vezérlőművelet például csak GET-kérelmek esetén fut. Annak érdekében, hogy minden kérés elérje az egyéni hibakezelő lapot, ne korlátozza azokat a HTTP-metódusok meghatározott készletére.
A kivételek eltérő kezelése az eredeti HTTP-módszer alapján:
- A Razor Pages esetében hozzon létre több kezelő metódusokat. Például a
OnGeta GET-kivételek kezelésére, míg aOnPosta POST-kivételek kezelésére használható. - MVC esetén http-igeattribútumokat alkalmazhat több műveletre. Például a
[HttpGet]a GET-kivételek kezelésére, míg a[HttpPost]a POST-kivételek kezelésére használható.
Ha engedélyezni szeretné, hogy a hitelesítés nélküli felhasználók megtekinthessék az egyéni hibakezelő lapot, győződjön meg arról, hogy támogatja a névtelen hozzáférést.
A kivétel elérése
Használja a IExceptionHandlerPathFeature elemet a kivétel és az eredeti kérési útvonal elérésére egy hibakezelőben. Az alábbi példa IExceptionHandlerPathFeature a kidobott kivételről nyújt további információt:
[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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
Kivételkezelő lambda
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését a válasz visszaadása előtt.
A következő kód egy lambdát használ a kivételkezeléshez:
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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
UseStatusCodePages
Alapértelmezés szerint egy ASP.NET Core-alkalmazás nem biztosít állapotkódlapot a HTTP-hibaállapot-kódokhoz, például 404 – Nem található. Amikor az alkalmazás beállít egy HTTP 400-599 hibaállapot-kódot, amely nem tartalmaz törzset, az állapotkódot és egy üres választörzset ad vissza. Ha engedélyezni szeretné az alapértelmezett csak szöveges kezelőket a gyakori hibaállapot-kódokhoz, hívja meg UseStatusCodePages a Program.cs-ben:
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePages();
Hívás UseStatusCodePages a köztes szoftverrel kapcsolatos kérések kezelése előtt. Hívja például a UseStatusCodePages parancsot a statikus fájlok köztes rétege és az Endpoints Middleware előtt.
Ha UseStatusCodePages nincs használatban, a végpont nélküli URL-címre való navigálás egy böngészőfüggő hibaüzenetet ad vissza, amely jelzi, hogy a végpont nem található. Amikor UseStatusCodePages a rendszer meghívja, a böngésző a következő választ adja vissza:
Status Code: 404; Not Found
UseStatusCodePages általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
Note
Az állapotkódlapok köztes szoftverei nem észlelnek kivételeket. Egyéni hibakezelő lap megadásához használja a kivételkezelő lapot.
UseStatusCodePages formátum sztring alkalmazásával
A válasz tartalomtípusának és szövegének testreszabásához használja azt a UseStatusCodePages túlterhelést, amely tartalomtípust és formázási sztringet vesz fel.
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}");
Az előző kódban a {0} egy helyőrző a hibakód számára.
UseStatusCodePages a formátumsztringet általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePages a lambda kifejezéssel
Az egyéni hibakezelési és válaszírási kód megadásához használja az UseStatusCodePages azon túlterhelését, amely elfogad egy lambda kifejezést:
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}");
});
A lambdát általában nem használják termelési környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
UseStatusCodePagesWithRedirects
A UseStatusCodePagesWithRedirects bővítmény metódusa:
- 302 – Talált állapotkódot küld az ügyfélnek.
- Átirányítja az ügyfelet az URL-sablonban megadott hibakezelési végpontra. A hibakezelő végpont általában hibainformációkat jelenít meg, és HTTP 200-et ad vissza.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");
Az URL-sablon tartalmazhat helyőrzőt {0} az állapotkódhoz, ahogyan az az előző kódban is látható. Ha az URL-sablon ~ (tilde) jellel kezdődik ~, akkor az ~ helyébe az alkalmazás PathBase kerül. Amikor végpontot ad meg az alkalmazásban, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják az alkalmazás esetében:
- Az ügyfelet egy másik végpontra kell átirányítani, általában olyan esetekben, amikor egy másik alkalmazás feldolgozza a hibát. Webalkalmazások esetén az ügyfél böngészőcímsávja az átirányított végpontot tükrözi.
- Ne őrizze meg és ne adja vissza az eredeti állapotkódot az első átirányítási válasznál.
UseStatusCodePagesWithReExecute
A UseStatusCodePagesWithReExecute bővítmény metódusa:
- Az eredeti állapotkódot adja vissza az ügyfélnek.
- A válasz törzsét úgy hozza létre, hogy egy másik elérési út használatával újra végrehajtja a kérelemfolyamatot.
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");
Ha az alkalmazásban egy végpont van megadva, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz.
Ezt a módszert gyakran használják, amikor az alkalmazásnak a következőt kell használnia:
- A kérés feldolgozása egy másik végpontra való átirányítás nélkül. Webalkalmazások esetén az ügyfél böngészőcímsávja az eredetileg kért végpontot tükrözi.
- Őrizze meg és adja vissza az eredeti állapotkódot a válaszsal együtt.
Az URL-sablonnak kezdődnie kell, / és tartalmaznia kell egy helyőrzőt {0} az állapotkódhoz. Ha az állapotkódot lekérdezési sztring paraméterként szeretné átadni, adjon át egy második argumentumot a következőbe UseStatusCodePagesWithReExecute: Például:
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");
A hibát feldolgozó végpont lekérheti a hibát létrehozó eredeti URL-címet, ahogyan az az alábbi példában látható:
[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);
}
}
}
Állapotkódlapok letiltása
MVC-vezérlő vagy műveleti metódus állapotkódlapjainak letiltásához használja a [SkipStatusCodePages] attribútumot.
Ha le szeretné tiltani az állapotkódlapokat a Razor Pages-kezelő metódusban vagy egy MVC-vezérlőben megadott kérésekhez, használja a következőt IStatusCodePagesFeature:
public void OnGet()
{
var statusCodePagesFeature =
HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature is not null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kivételkezelési kód
A kivételkezelő lapok kódjai kivételeket is okozhatnak. A gyártási hibaoldalakat alaposan tesztelni kell, és fokozottan ügyelni kell arra, hogy elkerüljük a sajátjaik által okozott kivételeket.
Válaszfejlécek
A válasz fejléceinek elküldése után:
- Az alkalmazás nem tudja módosítani a válasz állapotkódját.
- A kivételoldalak vagy -kezelők nem futtathatók. A választ be kell fejezni, vagy megszakadt a kapcsolat.
Kiszolgálói kivételkezelés
Az alkalmazások kivételkezelési logikája mellett a HTTP-kiszolgáló implementációja is képes kezelni néhány kivételt. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése előtt, a kiszolgáló választörzs nélkül küld 500 - Internal Server Error választ. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése után, a kiszolgáló bezárja a kapcsolatot. Az alkalmazás által nem kezelt kérelmeket a kiszolgáló kezeli. Minden kivételt, amely akkor fordul elő, amikor a kiszolgáló kezeli a kérést, a kiszolgáló kivételkezelése kezeli. Az alkalmazás egyéni hibaoldalai, a köztes szoftver kivételkezelése és a szűrők nem befolyásolják ezt a viselkedést.
Indítási kivétel kezelése
Csak az üzemeltetési réteg képes kezelni az alkalmazás indításakor előforduló kivételeket. A gazdagép konfigurálható az indítási hibák és a részletes hibák rögzítésére.
A fogadó réteg csak akkor jeleníthet meg hibalapot egy észlelt indítási hiba esetén, ha a hiba a gazdacím/port kötése után következik be. Ha a kötés sikertelen:
- Az üzemeltetési réteg kritikus kivételt naplóz.
- A dotnet-folyamat összeomlik.
- HTTP-kiszolgáló Kestrel állapotában nem jelenik meg hibaoldal.
Ha IIS-en (vagy Azure App Service-en) vagy IIS Expressen fut, az ASP.NET core modul502.5-ös folyamathibát ad vissza, ha a folyamat nem indítható el. További információ: ASP.NET Core hibaelhárítása az Azure App Service-ben és az IIS-ben.
Adatbázis hibaoldala
Az adatbázis fejlesztői lapjának kivételszűrője AddDatabaseDeveloperPageExceptionFilter rögzíti az adatbázissal kapcsolatos kivételeket, amelyek az Entity Framework Core migrálásával oldhatók meg. Ha ezek a kivételek előfordulnak, a rendszer HTML-választ hoz létre a probléma megoldásához szükséges lehetséges műveletek részleteivel. Ez a lap csak a fejlesztési környezetben engedélyezett. A következő kód hozzáadja az Adatbázis fejlesztői oldal kivételszűrőjét:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();
Kivételszűrők
Az MVC-alkalmazásokban a kivételszűrők globálisan, vezérlőnként vagy műveletenként konfigurálhatók. A Razor Pages-alkalmazásokban globálisan vagy oldalmodellenként konfigurálhatók. Ezek a szűrők kezelik a vezérlőművelet vagy egy másik szűrő végrehajtása során előforduló nem kezelt kivételeket. További információ: Szűrők a ASP.NET Core-ban.
A kivételszűrők hasznosak az MVC-műveletekben előforduló kivételek csapdába ejtéséhez, de nem olyan rugalmasak, mint a beépített kivételkezelő köztes szoftver, UseExceptionHandler. Javasoljuk, hogy használja UseExceptionHandler, kivéve, ha a hibakezelést a választott MVC-művelet alapján eltérő módon kell elvégeznie.
Modellállapot-hibák
A modellállapot-hibák kezelésével kapcsolatos információkért tekintse meg a modellkötést és a modellérvényesítést ismertető témakört.
További erőforrások
- Mintakód megtekintése vagy letöltése (hogyan töltsd le)
- Az Azure App Service és az IIS ASP.NET Core hibaelhárítása
- Gyakori hibák elhárítása az Azure App Service-ben és az IIS-ben az ASP.NET Core esetén
Kirk Larkin, Tom Dykstra és Steve Smith
Ez a cikk az ASP.NET Core-webalkalmazásokban előforduló hibák kezelésének gyakori megközelítéseit ismerteti. Lásd: A webes API-khoz készült ASP.NET Core API-k hibáinak kezelése .
Mintakód megtekintése vagy letöltése. (A letöltés menete.) Az F12 böngésző fejlesztői eszközeinek hálózati lapja hasznos a mintaalkalmazás tesztelése során.
Fejlesztői kivétel oldal
A Fejlesztői kivétel lap részletes információkat jelenít meg a nem kezelt kérelmek kivételeiről. A ASP.NET Core-sablonok a következő kódot generálják:
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();
});
}
Az előző kiemelt kód lehetővé teszi a fejlesztői kivételoldalt, ha az alkalmazás a fejlesztői környezetben fut.
A sablonok a köztes szoftver folyamatának korai szakaszában vannak elhelyezve UseDeveloperExceptionPage , hogy elkaphassák a következő köztes szoftverben kidobott kezeletlen kivételeket.
Az előző kód csak akkor engedélyezi a fejlesztői kivételoldalt, ha az alkalmazás a fejlesztői környezetben fut. A részletes kivételadatokat nem szabad nyilvánosan megjeleníteni, amikor az alkalmazás éles környezetben fut. További információ a környezetek konfigurálásáról: ASP.NET Core futtatókörnyezetek.
A Fejlesztői kivétel lap a következő információkat tartalmazhatja a kivételről és a kérésről:
- Verem nyomkövetése
- Sztringparaméterek lekérdezése, ha vannak ilyenek
- Cookie-k, ha vannak ilyenek
- Headers
A fejlesztői kivételoldal nem garantáltan biztosít semmilyen információt. Használja a naplózást a teljes hibainformációkhoz.
Kivételkezelő lap
Ha egyéni hibakezelő lapot szeretne konfigurálni az éles környezethez, hívja meg a következőt UseExceptionHandler: . Ez a kivételkezelés köztes szoftver:
- Naplózza a kezeletlen kivételeket.
- A kérést újra végrehajtja egy másik folyamatban a megadott elérési út használatával. A rendszer nem hajtja végre újra a kérést, ha a válasz elindult. A sablon által létrehozott kód újra végrehajtja a kérést az
/Errorelérési út használatával.
Warning
Ha az alternatív csővezeték saját kivételt dob, a Kivételkezelő köztes réteg újradobja az eredeti kivételt.
Az alábbi példában a UseExceptionHandler hozzáadja a kivételkezelő middleware-t a fejlesztési környezeteken kívüli környezetekben.
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
A Razor Lapok alkalmazássablon egy Hibalapot (.cshtml) és PageModel osztályt (ErrorModel) biztosít a Lapok mappában. MVC-alkalmazások esetén a projektsablon tartalmaz egy Error műveletmetódust és egy hibanézetet a Home vezérlőhöz.
A köztes szoftver kivételkezelése újra végrehajtja a kérést az eredeti HTTP-módszerrel. Ha egy hibakezelő végpont a HTTP-metódusok egy meghatározott halmazára korlátozódik, az csak az adott HTTP-metódusokhoz fut. Az attribútumot használó [HttpGet] MVC-vezérlőművelet például csak GET-kérelmek esetén fut. Annak érdekében, hogy minden kérés elérje az egyéni hibakezelő lapot, ne korlátozza azokat a HTTP-metódusok meghatározott készletére.
A kivételek eltérő kezelése az eredeti HTTP-módszer alapján:
- A Razor Pages esetében hozzon létre több kezelő metódusokat. Például a
OnGeta GET-kivételek kezelésére, míg aOnPosta POST-kivételek kezelésére használható. - MVC esetén http-igeattribútumokat alkalmazhat több műveletre. Például a
[HttpGet]a GET-kivételek kezelésére, míg a[HttpPost]a POST-kivételek kezelésére használható.
Ha engedélyezni szeretné, hogy a hitelesítés nélküli felhasználók megtekinthessék az egyéni hibakezelő lapot, győződjön meg arról, hogy támogatja a névtelen hozzáférést.
A kivétel elérése
Használja a IExceptionHandlerPathFeature elemet a kivétel és az eredeti kérési útvonal elérésére egy hibakezelőben. A következő kód hozzáadja ExceptionMessage az ASP.NET Core-sablonok által létrehozott alapértelmezett Pages/Error.cshtml.cs-hoz.
[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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
A kivétel tesztelése a mintaalkalmazásban:
- Állítsa be a környezetet élesre.
- Távolítsa el a megjegyzéseket a fájlból
webBuilder.UseStartup<Startup>();Program.cs. - Válassza a Kezdőlapon a Kivétel aktiválása lehetőséget.
Kivételkezelő lambda
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését a válasz visszaadása előtt.
A következő kód egy lambdát használ a kivételkezeléshez:
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
Ne osszon meg bizalmas hibainformációkat IExceptionHandlerFeature vagy IExceptionHandlerPathFeature az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
A lambda kivételkezelésének tesztelése a mintaalkalmazásban:
- Állítsa be a környezetet élesre.
- Távolítsa el a megjegyzéseket a fájlból
webBuilder.UseStartup<StartupLambda>();Program.cs. - Válassza a Kezdőlapon a Kivétel aktiválása lehetőséget.
UseStatusCodePages
Alapértelmezés szerint egy ASP.NET Core-alkalmazás nem biztosít állapotkódlapot a HTTP-hibaállapot-kódokhoz, például 404 – Nem található. Amikor az alkalmazás beállít egy HTTP 400-599 hibaállapot-kódot, amely nem tartalmaz törzset, az állapotkódot és egy üres választörzset ad vissza. Az állapotkódlapok megadásához használja az állapotkódlapok köztes szoftverét. Ha engedélyezni szeretné az alapértelmezett csak szöveges kezelőket a gyakori hibaállapot-kódokhoz, hívja meg UseStatusCodePages a Startup.Configure metódust:
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();
});
}
Hívás UseStatusCodePages a köztes szoftverrel kapcsolatos kérések kezelése előtt. Hívja például a UseStatusCodePages parancsot a statikus fájlok köztes rétege és az Endpoints Middleware előtt.
Ha UseStatusCodePages nincs használatban, a végpont nélküli URL-címre való navigálás egy böngészőfüggő hibaüzenetet ad vissza, amely jelzi, hogy a végpont nem található. Például a következőre navigálva: Home/Privacy2. Amikor UseStatusCodePages meghívják, a böngésző a következőt adja vissza:
Status Code: 404; Not Found
UseStatusCodePages általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
Tesztelés UseStatusCodePages a mintaalkalmazásban:
- Állítsa be a környezetet élesre.
- Távolítsa el a megjegyzéseket a fájlból
webBuilder.UseStartup<StartupUseStatusCodePages>();Program.cs. - Válassza ki a kezdőlap kezdőlapján található hivatkozásokat.
Note
Az állapotkódlapok köztes szoftverei nem észlelnek kivételeket. Egyéni hibakezelő lap megadásához használja a kivételkezelő lapot.
UseStatusCodePages formátum sztring alkalmazásával
A válasz tartalomtípusának és szövegének testreszabásához használja azt a UseStatusCodePages túlterhelést, amely tartalomtípust és formázási sztringet vesz fel.
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();
});
}
Az előző kódban a {0} egy helyőrző a hibakód számára.
UseStatusCodePages a formátumsztringet általában nem használják éles környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
A UseStatusCodePages való teszteléshez távolítsa el a megjegyzéseket a(z) webBuilder.UseStartup<StartupFormat>();-ból/ből.
UseStatusCodePages a lambda kifejezéssel
Az egyéni hibakezelési és válaszírási kód megadásához használja az UseStatusCodePages azon túlterhelését, amely elfogad egy lambda kifejezést:
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();
});
}
A lambdát általában nem használják termelési környezetben, mert olyan üzenetet ad vissza, amely nem hasznos a felhasználók számára.
A UseStatusCodePages való teszteléshez távolítsa el a megjegyzéseket a(z) webBuilder.UseStartup<StartupStatusLambda>();-ból/ből.
UseStatusCodePagesWithRedirects
A UseStatusCodePagesWithRedirects bővítmény metódusa:
- 302 – Talált állapotkódot küld az ügyfélnek.
- Átirányítja az ügyfelet az URL-sablonban megadott hibakezelési végpontra. A hibakezelő végpont általában hibainformációkat jelenít meg, és HTTP 200-et ad vissza.
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();
});
}
Az URL-sablon tartalmazhat helyőrzőt {0} az állapotkódhoz, ahogyan az az előző kódban is látható. Ha az URL-sablon ~ (tilde) jellel kezdődik ~, akkor az ~ helyébe az alkalmazás PathBase kerül. Amikor végpontot ad meg az alkalmazásban, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz. A Razor Pages példáért lásd a Pages/MyStatusCode.cshtml fájlt a mintaalkalmazásban.
Ezt a módszert gyakran használják az alkalmazás esetében:
- Az ügyfelet egy másik végpontra kell átirányítani, általában olyan esetekben, amikor egy másik alkalmazás feldolgozza a hibát. Webalkalmazások esetén az ügyfél böngészőcímsávja az átirányított végpontot tükrözi.
- Ne őrizze meg és ne adja vissza az eredeti állapotkódot az első átirányítási válasznál.
A UseStatusCodePages való teszteléshez távolítsa el a megjegyzéseket a(z) webBuilder.UseStartup<StartupSCredirect>();-ból/ből.
UseStatusCodePagesWithReExecute
A UseStatusCodePagesWithReExecute bővítmény metódusa:
- Az eredeti állapotkódot adja vissza az ügyfélnek.
- A válasz törzsét úgy hozza létre, hogy egy másik elérési út használatával újra végrehajtja a kérelemfolyamatot.
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();
});
}
Ha az alkalmazásban egy végpont van megadva, hozzon létre egy MVC-nézetet vagy Razor lapot a végponthoz. Győződjön meg arról, hogy UseStatusCodePagesWithReExecuteUseRouting elé kerüljön, így a kérelmet át lehet irányítani az állapotlapra. Egy Razor Pages példáért, lásd a Pages/MyStatusCode2.cshtml fájlt a mintapéldában.
Ezt a módszert gyakran használják, amikor az alkalmazásnak a következőt kell használnia:
- A kérés feldolgozása egy másik végpontra való átirányítás nélkül. Webalkalmazások esetén az ügyfél böngészőcímsávja az eredetileg kért végpontot tükrözi.
- Őrizze meg és adja vissza az eredeti állapotkódot a válaszsal együtt.
Az URL- és lekérdezési sztringsablonok tartalmazhatnak helyőrzőt {0} az állapotkódhoz. Az URL-sablonnak a következővel /kell kezdődnie: .
A hibát feldolgozó végpont lekérheti a hibát létrehozó eredeti URL-címet, ahogyan az az alábbi példában látható:
[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;
}
}
}
Egy Razor Pages példáért, lásd a Pages/MyStatusCode2.cshtml fájlt a mintapéldában.
A UseStatusCodePages való teszteléshez távolítsa el a megjegyzéseket a(z) webBuilder.UseStartup<StartupSCreX>();-ból/ből.
Állapotkódlapok letiltása
MVC-vezérlő vagy műveleti metódus állapotkódlapjainak letiltásához használja a [SkipStatusCodePages] attribútumot.
Ha le szeretné tiltani az állapotkódlapokat a Razor Pages-kezelő metódusban vagy egy MVC-vezérlőben megadott kérésekhez, használja a következőt IStatusCodePagesFeature:
public void OnGet()
{
// using Microsoft.AspNetCore.Diagnostics;
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
}
Kivételkezelési kód
A kivételkezelő lapok kódjai kivételeket is okozhatnak. A gyártási hibaoldalakat alaposan tesztelni kell, és fokozottan ügyelni kell arra, hogy elkerüljük a sajátjaik által okozott kivételeket.
Válaszfejlécek
A válasz fejléceinek elküldése után:
- Az alkalmazás nem tudja módosítani a válasz állapotkódját.
- A kivételoldalak vagy -kezelők nem futtathatók. A választ be kell fejezni, vagy megszakadt a kapcsolat.
Kiszolgálói kivételkezelés
Az alkalmazások kivételkezelési logikája mellett a HTTP-kiszolgáló implementációja is képes kezelni néhány kivételt. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése előtt, a kiszolgáló választörzs nélkül küld 500 - Internal Server Error választ. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése után, a kiszolgáló bezárja a kapcsolatot. Az alkalmazás által nem kezelt kérelmeket a kiszolgáló kezeli. Minden kivételt, amely akkor fordul elő, amikor a kiszolgáló kezeli a kérést, a kiszolgáló kivételkezelése kezeli. Az alkalmazás egyéni hibaoldalai, a köztes szoftver kivételkezelése és a szűrők nem befolyásolják ezt a viselkedést.
Indítási kivétel kezelése
Csak az üzemeltetési réteg képes kezelni az alkalmazás indításakor előforduló kivételeket. A gazdagép konfigurálható az indítási hibák és a részletes hibák rögzítésére.
A fogadó réteg csak akkor jeleníthet meg hibalapot egy észlelt indítási hiba esetén, ha a hiba a gazdacím/port kötése után következik be. Ha a kötés sikertelen:
- Az üzemeltetési réteg kritikus kivételt naplóz.
- A dotnet-folyamat összeomlik.
- HTTP-kiszolgáló Kestrel állapotában nem jelenik meg hibaoldal.
Ha IIS-en (vagy Azure App Service-en) vagy IIS Expressen fut, az ASP.NET core modul502.5-ös folyamathibát ad vissza, ha a folyamat nem indítható el. További információ: ASP.NET Core hibaelhárítása az Azure App Service-ben és az IIS-ben.
Adatbázis hibaoldala
Az adatbázis fejlesztői lapjának kivételszűrője AddDatabaseDeveloperPageExceptionFilter rögzíti az adatbázissal kapcsolatos kivételeket, amelyek az Entity Framework Core migrálásával oldhatók meg. Ha ezek a kivételek előfordulnak, a rendszer HTML-választ hoz létre a probléma megoldásához szükséges lehetséges műveletek részleteivel. Ez a lap csak a fejlesztési környezetben engedélyezett. Az egyes felhasználói fiókok megadásakor a ASP.NET Core Razor Pages-sablonok a következő kódot hozták létre:
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();
}
Kivételszűrők
Az MVC-alkalmazásokban a kivételszűrők globálisan, vezérlőnként vagy műveletenként konfigurálhatók. A Razor Pages-alkalmazásokban globálisan vagy oldalmodellenként konfigurálhatók. Ezek a szűrők kezelik a vezérlőművelet vagy egy másik szűrő végrehajtása során előforduló nem kezelt kivételeket. További információ: Szűrők a ASP.NET Core-ban.
A kivételszűrők hasznosak az MVC-műveletekben előforduló kivételek csapdába ejtéséhez, de nem olyan rugalmasak, mint a beépített kivételkezelő köztes szoftver, UseExceptionHandler. Javasoljuk, hogy használja UseExceptionHandler, kivéve, ha a hibakezelést a választott MVC-művelet alapján eltérő módon kell elvégeznie.
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();
});
}
Modellállapot-hibák
A modellállapot-hibák kezelésével kapcsolatos információkért tekintse meg a modellkötést és a modellérvényesítést ismertető témakört.
További erőforrások
- Az Azure App Service és az IIS ASP.NET Core hibaelhárítása
- Gyakori hibák elhárítása az Azure App Service-ben és az IIS-ben az ASP.NET Core esetén
Ez a cikk az ASP.NET Core-webalkalmazásokban előforduló hibák kezelésének gyakori megközelítéseit ismerteti. Lásd: A webes API-khoz készült ASP.NET Core API-k hibáinak kezelése .
Mintakód megtekintése vagy letöltése. (A letöltés menete.)
Fejlesztői kivétel oldal
A Fejlesztői kivétel lap részletes információkat jelenít meg a kérelemkivételekről. A ASP.NET Core-sablonok a következő kódot generálják:
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
Az előző kód lehetővé teszi a fejlesztői kivételoldalt, ha az alkalmazás a fejlesztői környezetben fut.
A sablonok a UseDeveloperExceptionPage elemet minden köztes szoftver elé helyezik, így a következő köztes szoftverben fogják elkapni a kivételeket.
Az előző kód csak akkor engedélyezi a fejlesztői kivételoldalt , ha az alkalmazás a fejlesztői környezetben fut. A részletes kivételadatok nem jeleníthetők meg nyilvánosan, amikor az alkalmazás éles környezetben fut. További információ a környezetek konfigurálásáról: ASP.NET Core futtatókörnyezetek.
A Fejlesztői kivétel lap a következő információkat tartalmazza a kivételről és a kérésről:
- Verem nyomkövetése
- Sztringparaméterek lekérdezése, ha vannak ilyenek
- Cookie-k, ha vannak ilyenek
- Headers
Kivételkezelő lap
Ha egyéni hibakezelő oldalt szeretne konfigurálni az éles környezethez, használja az Exception Handling Middleware-t. A köztes szoftver:
- Fogások és naplók kivételei.
- Újra végrehajtja a kérést egy másik folyamatban a megjelölt lap vagy vezérlő számára. A rendszer nem hajtja végre újra a kérést, ha a válasz elindult. A sablon által létrehozott kód újravégrehajtja a kérést a következőre:
/Error.
Az alábbi példában, UseExceptionHandler hozzáadja a Kivételkezelési köztes szoftvert a fejlesztési környezeten kívüli esetekben.
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
A Razor Lapok alkalmazássablon egy Hibalapot (.cshtml) és PageModel osztályt (ErrorModel) biztosít a Lapok mappában. MVC-alkalmazások esetén a projektsablon tartalmaz egy hibaműveleti módszert és egy hibanézetet a Home vezérlőben.
Ne jelölje meg a hibakezelő műveleti metódust HTTP-metódusattribútumokkal, például HttpGet. Az explicit igék megakadályozzák, hogy egyes kérések elérjék a metódust. Engedélyezze a névtelen hozzáférést a metódushoz, ha a hitelesítés nélküli felhasználóknak látniuk kell a hibanézetet.
A kivétel elérése
A hibakezelő vezérlőben vagy lapon használja a IExceptionHandlerPathFeature kódot a kivétel és az eredeti kérés útvonalának eléréséhez.
[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
Ne szolgáljon ki bizalmas hibainformációkat az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
A kivételkezelési oldal aktiválásához állítsa a környezetet éles módra, és idézze elő a kivételt.
Kivételkezelő lambda
Az egyéni kivételkezelő lap alternatívájaként lambda adható meg a UseExceptionHandler-nek. A lambda használata lehetővé teszi a hiba elérését a válasz visszaadása előtt.
Íme egy példa a lambda kivételkezelésre való használatára:
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();
}
Az előző kódban hozzáadásra kerül a await context.Response.WriteAsync(new string(' ', 512));, hogy az Internet Explorer böngésző ne egy IE-hibaüzenetet, hanem maga a hibaüzenetet jelenítse meg. További információkért tekintse meg ezt a GitHub-problémát.
Warning
Ne osszon meg bizalmas hibainformációkat IExceptionHandlerFeature vagy IExceptionHandlerPathFeature az ügyfeleknek. A hibák kiszolgálása biztonsági kockázatot jelent.
Ha meg szeretné tekinteni a lambda kivételkezelésének eredményét a mintaalkalmazásban, használja az és ProdEnvironment az ErrorHandlerLambda előfeldolgozási irányelveket, és válassza a Kezdőlapon a Kivétel aktiválása lehetőséget.
UseStatusCodePages
Alapértelmezés szerint egy ASP.NET Core-alkalmazás nem biztosít állapotkódlapot a HTTP-állapotkódokhoz, például 404 – Nem található. Az alkalmazás egy állapotkódot és egy üres választörzset ad vissza. Állapotkódlapok megadásához használja az Állapotkódlapok köztes szoftvert.
A köztes szoftvert a Microsoft.AspNetCore.Diagnostics csomag teszi elérhetővé.
Ha engedélyezni szeretné az alapértelmezett csak szöveges kezelőket a gyakori hibaállapot-kódokhoz, hívja meg UseStatusCodePages a Startup.Configure metódust:
app.UseStatusCodePages();
Hívja meg a UseStatusCodePages igénykezelő köztes szoftvert (például a statikus fájl köztes szoftvert és az MVC köztes szoftvert) kezelése előtt.
Ha UseStatusCodePages nincs használatban, a végpont nélküli URL-címre való navigálás egy böngészőfüggő hibaüzenetet ad vissza, amely jelzi, hogy a végpont nem található. Például a következőre navigálva: Home/Privacy2. Amikor UseStatusCodePages meghívják, a böngésző a következőt adja vissza:
Status Code: 404; Not Found
UseStatusCodePages formátum sztring alkalmazásával
A válasz tartalomtípusának és szövegének testreszabásához használja azt a UseStatusCodePages túlterhelést, amely tartalomtípust és formázási sztringet vesz fel.
app.UseStatusCodePages(
"text/plain", "Status code page, status code: {0}");
UseStatusCodePages a lambda kifejezéssel
Az egyéni hibakezelési és válaszírási kód megadásához használja az UseStatusCodePages azon túlterhelését, amely elfogad egy lambda kifejezést:
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
A UseStatusCodePagesWithRedirects bővítmény metódusa:
- 302 – Talált állapotkódot küld az ügyfélnek.
- Átirányítja az ügyfelet az URL-sablonban megadott helyre.
app.UseStatusCodePagesWithRedirects("/StatusCode?code={0}");
Az URL-sablon tartalmazhat helyőrzőt {0} az állapotkódhoz, ahogyan az a példában is látható. Ha az URL-sablon ~ (tilde) jellel kezdődik ~, akkor az ~ helyébe az alkalmazás PathBase kerül. Ha az alkalmazásban egy végpontra mutat, hozzon létre egy MVC nézetet vagy Razor lapot a végponthoz.
Razor Példaként a Pages/StatusCode.cshtml oldalt lásd a mintaalkalmazásban.
Ezt a módszert gyakran használják az alkalmazás esetében:
- Az ügyfelet egy másik végpontra kell átirányítani, általában olyan esetekben, amikor egy másik alkalmazás feldolgozza a hibát. Webalkalmazások esetén az ügyfél böngészőcímsávja az átirányított végpontot tükrözi.
- Ne őrizze meg és ne adja vissza az eredeti állapotkódot az első átirányítási válasznál.
UseStatusCodePagesWithReExecute
A UseStatusCodePagesWithReExecute bővítmény metódusa:
- Az eredeti állapotkódot adja vissza az ügyfélnek.
- A válasz törzsét úgy hozza létre, hogy egy másik elérési út használatával újra végrehajtja a kérelemfolyamatot.
app.UseStatusCodePagesWithReExecute("/StatusCode","?code={0}");
Ha az alkalmazásban egy végpontra mutat, hozzon létre egy MVC nézetet vagy Razor lapot a végponthoz. Győződjön meg arról, hogy UseStatusCodePagesWithReExecuteUseRouting elé kerüljön, így a kérelmet át lehet irányítani az állapotlapra.
Razor Példaként a Pages/StatusCode.cshtml oldalt lásd a mintaalkalmazásban.
Ezt a módszert gyakran használják, amikor az alkalmazásnak a következőt kell használnia:
- A kérés feldolgozása egy másik végpontra való átirányítás nélkül. Webalkalmazások esetén az ügyfél böngészőcímsávja az eredetileg kért végpontot tükrözi.
- Őrizze meg és adja vissza az eredeti állapotkódot a válaszsal együtt.
Az URL- és lekérdezési sztringsablonok tartalmazhatnak helyőrzőt ({0}) az állapotkódhoz. Az URL-sablonnak perjellel (/perjellel) kell kezdődnie. Ha helyőrzőt használ az elérési úton, győződjön meg arról, hogy a végpont (oldal vagy vezérlő) feldolgozhatja az elérési út szegmensét. Például egy hibaoldalnak támogatnia kell az opcionális útvonal szegmens értékét az Razor irányelvvel:
@page "{code?}"
A hibát feldolgozó végpont lekérheti a hibát létrehozó eredeti URL-címet, ahogyan az az alábbi példában látható:
var statusCodeReExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature != null)
{
OriginalURL =
statusCodeReExecuteFeature.OriginalPathBase
+ statusCodeReExecuteFeature.OriginalPath
+ statusCodeReExecuteFeature.OriginalQueryString;
}
Ne jelölje meg a hibakezelő műveleti metódust HTTP-metódusattribútumokkal, például HttpGet. Az explicit igék megakadályozzák, hogy egyes kérések elérjék a metódust. Engedélyezze a névtelen hozzáférést a metódushoz, ha a hitelesítés nélküli felhasználóknak látniuk kell a hibanézetet.
Állapotkódlapok letiltása
Ha le szeretné tiltani egy MVC-vezérlő vagy műveleti módszer állapotkódlapjait, használja az [SkipStatusCodePages] attribútumot.
Ha le szeretné tiltani az állapotkódlapokat a Razor Pages-kezelő metódusban vagy egy MVC-vezérlőben megadott kérésekhez, használja a következőt IStatusCodePagesFeature:
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
Kivételkezelési kód
A kivételkezelő lapok kódjai kivételeket okozhatnak. Gyakran jó ötlet, ha az éles hibaoldalak csak statikus tartalomból állnak.
Válaszfejlécek
A válasz fejléceinek elküldése után:
- Az alkalmazás nem tudja módosítani a válasz állapotkódját.
- A kivételoldalak vagy -kezelők nem futtathatók. A választ be kell fejezni, vagy megszakadt a kapcsolat.
Kiszolgálói kivételkezelés
Az alkalmazás kivételkezelési logikája mellett a HTTP-kiszolgáló implementációja is képes kezelni néhány kivételt. Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése előtt, a kiszolgáló választörzs nélkül küld egy 500 – belső kiszolgálói hibaválaszt . Ha a kiszolgáló kivételt kap a válaszfejlécek elküldése után, a kiszolgáló bezárja a kapcsolatot. Az alkalmazás által nem kezelt kérelmeket a kiszolgáló kezeli. Minden kivételt, amely akkor fordul elő, amikor a kiszolgáló kezeli a kérést, a kiszolgáló kivételkezelése kezeli. Az alkalmazás egyéni hibaoldalai, a köztes szoftver kivételkezelése és a szűrők nem befolyásolják ezt a viselkedést.
Indítási kivétel kezelése
Csak az üzemeltetési réteg képes kezelni az alkalmazás indításakor előforduló kivételeket. A gazdagép konfigurálható az indítási hibák és a részletes hibák rögzítésére.
A fogadó réteg csak akkor jeleníthet meg hibalapot egy észlelt indítási hiba esetén, ha a hiba a gazdacím/port kötése után következik be. Ha a kötés sikertelen:
- Az üzemeltetési réteg kritikus kivételt naplóz.
- A dotnet-folyamat összeomlik.
- HTTP-kiszolgáló Kestrel állapotában nem jelenik meg hibaoldal.
Ha IIS-en (vagy Azure App Service-en) vagy IIS Expressen fut, az ASP.NET core modul502.5-ös folyamathibát ad vissza, ha a folyamat nem indítható el. További információ: ASP.NET Core hibaelhárítása az Azure App Service-ben és az IIS-ben.
Adatbázis hibaoldala
Az Adatbázis Hibalap köztes szoftver rögzíti az adatbázissal kapcsolatos kivételeket, amelyeket az Entity Framework migráció alkalmazásával lehet megoldani. Amikor ilyen kivételek lépnek fel, a rendszer html-választ ad a probléma megoldásához szükséges lehetséges műveletek részleteivel. Ezt a lapot csak a fejlesztési környezetben szabad engedélyezni. Engedélyezze a lapot úgy, hogy kódot ad hozzá a következőhöz Startup.Configure:
if (env.IsDevelopment())
{
app.UseDatabaseErrorPage();
}
UseDatabaseErrorPage A Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet csomag szükséges.
Kivételszűrők
Az MVC-alkalmazásokban a kivételszűrők globálisan, vezérlőnként vagy műveletenként konfigurálhatók. A Razor Pages-alkalmazásokban globálisan vagy oldalmodellenként konfigurálhatók. Ezek a szűrők kezelik azokat a kezeletlen kivételeket, amelyek egy vezérlőművelet vagy egy másik szűrő végrehajtása során fordulnak elő. További információ: Szűrők a ASP.NET Core-ban.
Tip
A kivétel-szűrők hasznosak az MVC-műveletekben előforduló kivételek kezelésére, de nem olyan rugalmasak, mint a kivételkezelő köztes szoftver. A köztes szoftver használatát javasoljuk. Csak akkor használjon szűrőket, ha a hibakezelést a választott MVC-művelet alapján eltérő módon kell elvégeznie.
Modellállapot-hibák
A modellállapot-hibák kezelésével kapcsolatos információkért tekintse meg a modellkötést és a modellérvényesítést ismertető témakört.
További erőforrások
- Az Azure App Service és az IIS ASP.NET Core hibaelhárítása
- Gyakori hibák elhárítása az Azure App Service-ben és az IIS-ben az ASP.NET Core esetén