ASP.NET Core hatalarını işleme

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.

Tarafından Tom Dykstra

Bu makalede, ASP.NET Core web uygulamalarında hataları işlemeye yönelik yaygın yaklaşımlar ele alınıyor. Ayrıca bkz. ASP.NET Core web API'lerindeki hataları işleme ve Minimum API uygulamalarında hataları işleme.

Geliştirici özel durum sayfası

Geliştirici Özel Durum Sayfası, işlenmeyen istek özel durumları hakkında ayrıntılı bilgiler görüntüler. ASP.NET Core uygulamaları, her ikisi de aşağıdaki durumlarda varsayılan olarak geliştirici özel durum sayfasını etkinleştirir:

  • Geliştirme ortamında çalıştırılıyor.
  • Geçerli şablonlarla, yani WebApplication.CreateBuilder kullanılarak oluşturulan uygulama. kullanılarak oluşturulan uygulamalar, WebHost.CreateDefaultBuilder içinde Configurearayarak app.UseDeveloperExceptionPage geliştirici özel durum sayfasını etkinleştirmelidir.

Geliştirici özel durum sayfası ara yazılım işlem hattında erken çalıştırılır, böylece izleyen ara yazılımda işlenmeyen özel durumları yakalayabilir.

Uygulama Üretim ortamında çalıştırıldığında ayrıntılı özel durum bilgileri genel olarak görüntülenmemelidir. Ortamları yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma.

Geliştirici Özel Durum Sayfası, özel durum ve istek hakkında aşağıdaki bilgileri içerebilir:

  • Yığın izleme
  • Varsa sorgu dizesi parametreleri
  • Cookies, varsa
  • Üst Bilgiler
  • Varsa uç nokta meta verileri

Aşağıdaki görüntüde Yönlendirme seçili ve uç nokta meta verilerinin görüntülendiği örnek bir geliştirici özel durum sayfası gösterilmektedir:

Yönlendirme'nin seçili olduğu ve uç nokta meta verilerinin görüntülendiği geliştirici özel durum sayfası

Geliştirici Özel Durum Sayfası'nın herhangi bir bilgi sağlaması garanti değildir. Tam hata bilgileri için Günlüğe Kaydetme özelliğini kullanın.

Özel durum işleyici sayfası

Üretim ortamı için özel bir hata işleme sayfası yapılandırmak için öğesini çağırınUseExceptionHandler. Ara yazılımı işleyen bu özel durum:

  • İşlenmeyen özel durumları yakalar ve günlüğe kaydeder.
  • Belirtilen yolu kullanarak isteği alternatif bir işlem hattında yeniden yürütür. Yanıt başlatıldıysa istek yeniden yürütülemez. Şablon tarafından oluşturulan kod, yolu kullanarak isteği yeniden yürütür /Error .

Uyarı

Alternatif işlem hattı kendi özel durumu oluşturursa, Özel Durum İşleme Ara Yazılımı özgün özel durumu yeniden oluşturur.

Bu ara yazılım istek işlem hattını yeniden yürütebileceğinden:

  • Ara yazılımların yeniden giriş işlemini aynı istekle işlemesi gerekir. Bu normalde, çağrısından _next sonra durumlarını temizleme veya işlemi yeniden yapmaktan kaçınmak için üzerindeki işlemlerini HttpContext önbelleğe alma anlamına gelir. İstek gövdesiyle ilgilenirken bu, Sonuçları Form okuyucusu gibi arabelleğe alma veya önbelleğe alma anlamına gelir.
  • UseExceptionHandler(IApplicationBuilder, String) Şablonlarda kullanılan aşırı yükleme için yalnızca istek yolu değiştirilir ve yol verileri temizlenir. Üst bilgiler, yöntem ve öğeler gibi istek verilerinin tümü olduğu gibi yeniden kullanılır.
  • Kapsamı belirlenmiş hizmetler aynı kalır.

Aşağıdaki örnekte, UseExceptionHandler Geliştirme dışı ortamlarda özel durum işleme ara yazılımını ekler:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Sayfalar uygulama şablonu, Razor Sayfalar klasöründe bir Hata sayfası (.cshtml) ve PageModel sınıf (ErrorModel) sağlar. Bir MVC uygulaması için proje şablonu, denetleyici için Home bir Error eylem yöntemi ve Hata görünümü içerir.

Özel durum işleme ara yazılımı özgün HTTP yöntemini kullanarak isteği yeniden yürütür. Hata işleyicisi uç noktası belirli bir HTTP yöntemleri kümesiyle sınırlıysa, yalnızca bu HTTP yöntemleri için çalışır. Örneğin, özniteliğini kullanan [HttpGet] bir MVC denetleyicisi eylemi yalnızca GET istekleri için çalıştırılır. Tüm isteklerin özel hata işleme sayfasına ulaştığından emin olmak için bunları belirli bir HTTP yöntemleri kümesiyle kısıtlamayın.

Özel durumları özgün HTTP yöntemine göre farklı şekilde işlemek için:

  • Sayfalar için Razor birden çok işleyici yöntemi oluşturun. Örneğin, GET özel durumlarını işlemek için kullanın OnGet ve POST özel durumlarını işlemek için kullanın OnPost .
  • MVC için, birden çok eyleme HTTP fiili öznitelikleri uygulayın. Örneğin, GET özel durumlarını işlemek için kullanın [HttpGet] ve POST özel durumlarını işlemek için kullanın [HttpPost] .

Kimliği doğrulanmamış kullanıcıların özel hata işleme sayfasını görüntülemesine izin vermek için anonim erişimi desteklediğinden emin olun.

Özel duruma erişme

Hata işleyicisinde özel duruma ve özgün istek yoluna erişmek için kullanın IExceptionHandlerPathFeature . Aşağıdaki örnek, oluşturulan özel durum hakkında daha fazla bilgi almak için kullanır IExceptionHandlerPathFeature :

[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.";
        }
    }
}

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Özel durum işleyici lambda

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak, yanıtı döndürmeden önce hataya erişim sağlar.

Aşağıdaki kod özel durum işleme için bir lambda kullanır:

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

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

IExceptionHandler

IExceptionHandler , geliştiriciye merkezi bir konumda bilinen özel durumları işlemek için geri çağırma sağlayan bir arabirimdir.

IExceptionHandler uygulamaları çağrılarak IServiceCollection.AddExceptionHandler<T>kaydedilir. Bir IExceptionHandler örneğin ömrü tekildir. Birden çok uygulama eklenebilir ve bunlar kayıtlı sırayla çağrılır.

Bir özel durum işleyicisi bir isteği işlerse, işlemeyi durdurmak için geri dönebilir true . Bir özel durum işleyicisi herhangi bir özel durum işleyicisi tarafından işlenmezse denetim, ara yazılımdaki varsayılan davranışa ve seçeneklere geri döner. İşlenen ve işlenmeyen özel durumlar için farklı ölçümler ve günlükler yayılır.

Aşağıdaki örnekte bir IExceptionHandler uygulama gösterilmektedir:

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

Aşağıdaki örnekte, bağımlılık ekleme için bir IExceptionHandler uygulamanın nasıl kaydedilecekleri gösterilmektedir:

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

Yukarıdaki kod Geliştirme ortamında çalıştırıldığında:

  • CustomExceptionHandler bir özel durumu işlemek için ilk olarak çağrılır.
  • Özel durumu günlüğe kaydettikten sonra yöntemi döndürürfalse, TryHandleException bu nedenle geliştirici özel durum sayfası gösterilir.

Diğer ortamlarda:

  • CustomExceptionHandler bir özel durumu işlemek için ilk olarak çağrılır.
  • Özel durumu TryHandleException günlüğe kaydettikten sonra yöntemi döndürür false, böylece /Error sayfa gösterilir.

UseStatusCodePages

Varsayılan olarak, ASP.NET Core uygulaması HTTP hata durum kodları için 404 - Bulunamadı gibi bir durum kodu sayfası sağlamaz. Uygulama gövdesi olmayan bir HTTP 400-599 hata durum kodu ayarladığında, durum kodunu ve boş bir yanıt gövdesini döndürür. Yaygın hata durum kodları için varsayılan yalnızca metin işleyicilerini etkinleştirmek için çağrısında UseStatusCodePages kullanın Program.cs:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages();

İstek işleme ara yazılımından önce çağırın UseStatusCodePages . Örneğin, Statik Dosya Ara Yazılımı ve Uç Noktalar Ara Yazılımı'nın önünde çağırın UseStatusCodePages .

Kullanılmadığında UseStatusCodePages , uç nokta olmadan URL'ye gitmek, uç noktanın bulunamadığını belirten tarayıcıya bağlı bir hata iletisi döndürür. Çağrıldığında UseStatusCodePages , tarayıcı aşağıdaki yanıtı döndürür:

Status Code: 404; Not Found

UseStatusCodePages genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

Not

Durum kodu sayfaları ara yazılımı özel durumları yakalamaz. Özel hata işleme sayfası sağlamak için özel durum işleyici sayfasını kullanın.

Biçim dizesi ile UseStatusCodePages

Yanıt içerik türünü ve metnini özelleştirmek için, bir içerik türü ve biçim dizesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

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}");

Yukarıdaki kodda, {0} hata kodu için bir yer tutucudur.

UseStatusCodePages kullanıcılar için yararlı olmayan bir ileti döndürdüğü için, biçim dizesi genellikle üretimde kullanılmaz.

Lambda ile UseStatusCodePages

Özel hata işleme ve yanıt yazma kodu belirtmek için bir lambda ifadesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages(async statusCodeContext =>
{
    // using static System.Net.Mime.MediaTypeNames;
    statusCodeContext.HttpContext.Response.ContentType = Text.Plain;

    await statusCodeContext.HttpContext.Response.WriteAsync(
        $"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});

UseStatusCodePages lambda ile genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects Uzantı yöntemi:

  • İstemciye bir 302 - Bulundu durum kodu gönderir.
  • İstemciyi URL şablonunda sağlanan hata işleme uç noktasına yönlendirir. Hata işleme uç noktası genellikle hata bilgilerini görüntüler ve HTTP 200 döndürür.
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");

URL şablonu, önceki kodda gösterildiği gibi durum kodu için bir {0} yer tutucu içerebilir. URL şablonu (tilde) ile ~ başlıyorsa, ~ yerine uygulamanın PathBaseolur. Uygulamada bir uç nokta belirtirken, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulama şu durumlarda kullanılır:

  • genellikle farklı bir uygulamanın hatayı işlediği durumlarda istemciyi farklı bir uç noktaya yönlendirmelidir. Web uygulamaları için istemcinin tarayıcı adres çubuğu yeniden yönlendirilen uç noktayı yansıtır.
  • İlk yeniden yönlendirme yanıtıyla özgün durum kodunu korumamalı ve döndürmemelidir.

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute Uzantı yöntemi:

  • Alternatif bir yol kullanarak istek işlem hattını yeniden yürüterek yanıt gövdesini oluşturur.
  • İşlem hattı yeniden yürütülmeden önce veya sonra durum kodunu değiştirmez.

Yeni işlem hattı, durum kodu üzerinde tam denetime sahip olduğundan yeni işlem hattı yürütmesi yanıtın durum kodunu değiştirebilir. Yeni işlem hattı durum kodunu değiştirmezse, özgün durum kodu istemciye gönderilir.

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");

Uygulama içinde bir uç nokta belirtilirse, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulamanın aşağıdakileri yapması gerektiğinde kullanılır:

  • İsteği farklı bir uç noktaya yeniden yönlendirmeden işleyin. Web uygulamaları için istemcinin tarayıcı adres çubuğu başlangıçta istenen uç noktayı yansıtır.
  • Yanıtla birlikte özgün durum kodunu koruyun ve döndürin.

URL şablonu ile / başlamalıdır ve durum kodu için bir yer tutucu {0} içerebilir. Durum kodunu sorgu dizesi parametresi olarak geçirmek için içine ikinci bir bağımsız değişken UseStatusCodePagesWithReExecutegeçirin. Örneğin:

var app = builder.Build();  
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");

Hatayı işleyen uç nokta, aşağıdaki örnekte gösterildiği gibi hatayı oluşturan özgün URL'yi alabilir:

[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);
        }
    }
}

Bu ara yazılım istek işlem hattını yeniden yürütebileceğinden:

  • Ara yazılımların yeniden giriş işlemini aynı istekle işlemesi gerekir. Bu normalde, çağrısından _next sonra durumlarını temizleme veya işlemi yeniden yapmaktan kaçınmak için üzerindeki işlemlerini HttpContext önbelleğe alma anlamına gelir. İstek gövdesiyle ilgilenirken bu, Sonuçları Form okuyucusu gibi arabelleğe alma veya önbelleğe alma anlamına gelir.
  • Kapsamı belirlenmiş hizmetler aynı kalır.

Durum kodu sayfalarını devre dışı bırakma

MVC denetleyicisinin veya eylem yönteminin durum kodu sayfalarını devre dışı bırakmak için [SkipStatusCodePages] özniteliğini kullanın.

Pages işleyici yönteminde veya MVC denetleyicisinde Razor belirli istekler için durum kodu sayfalarını devre dışı bırakmak için kullanın IStatusCodePagesFeature:

public void OnGet()
{
    var statusCodePagesFeature =
        HttpContext.Features.Get<IStatusCodePagesFeature>();

    if (statusCodePagesFeature is not null)
    {
        statusCodePagesFeature.Enabled = false;
    }
}

Özel durum işleme kodu

Özel durum işleme sayfalarındaki kod da özel durumlar oluşturabilir. Üretim hata sayfaları kapsamlı bir şekilde test edilmeli ve kendi özel durumlarının oluşmasını önlemek için ek özen gösterilmelidir.

Yanıt üst bilgileri

Yanıtın üst bilgileri gönderildikten sonra:

  • Uygulama yanıtın durum kodunu değiştiremez.
  • Özel durum sayfaları veya işleyicileri çalıştırılamaz. Yanıt tamamlanmalıdır veya bağlantı durdurulmalıdır.

Sunucu özel durum işleme

Bir uygulamadaki özel durum işleme mantığına ek olarak, HTTP sunucusu uygulaması bazı özel durumları işleyebilir. Sunucu yanıt üst bilgileri gönderilmeden önce bir özel durum yakalarsa, yanıt gövdesi olmadan bir 500 - Internal Server Error yanıt gönderir. Yanıt üst bilgileri gönderildikten sonra sunucu bir özel durum yakalarsa, sunucu bağlantıyı kapatır. Uygulama tarafından işlenmemiş istekler sunucu tarafından işlenir. Sunucu isteği işlerken oluşan özel durumlar, sunucunun özel durum işlemesi tarafından işlenir. Uygulamanın özel hata sayfaları, özel durum işleme ara yazılımı ve filtreler bu davranışı etkilemez.

Özel durum işlemeyi başlatma

Yalnızca barındırma katmanı, uygulama başlatma sırasında gerçekleşen özel durumları işleyebilir. Konak, başlangıç hatalarını yakalamak ve ayrıntılı hataları yakalamak için yapılandırılabilir.

Barındırma katmanı, yakalanan başlatma hatası için yalnızca ana bilgisayar adresi/bağlantı noktası bağlaması sonrasında hata oluşması durumunda bir hata sayfası gösterebilir. Bağlama başarısız olursa:

  • Barındırma katmanı kritik bir özel durumu günlüğe kaydeder.
  • dotnet işlemi kilitleniyor.
  • HTTP sunucusu olduğunda hiçbir hata sayfası görüntülenmez Kestrel.

IIS (veya Azure Uygulaması Hizmeti) veya IIS Express üzerinde çalışırken, işlem başlatılamıyorsa ASP.NET Çekirdek Modülü tarafından 502.5 - İşlem Hatası döndürülür. Daha fazla bilgi için bkz. Azure Uygulaması Hizmeti ve IIS'de ASP.NET Core sorunlarını giderme.

Veritabanı hata sayfası

Veritabanı geliştirici sayfası özel durum filtresi AddDatabaseDeveloperPageExceptionFilter , Entity Framework Core geçişleri kullanılarak çözümlenebilen veritabanıyla ilgili özel durumları yakalar. Bu özel durumlar oluştuğunda, sorunu çözmek için olası eylemlerin ayrıntılarıyla birlikte bir HTML yanıtı oluşturulur. Bu sayfa yalnızca Geliştirme ortamında etkinleştirilir. Aşağıdaki kod, Veritabanı geliştirici sayfası özel durum filtresini ekler:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();

Özel durum filtreleri

MVC uygulamalarında özel durum filtreleri genel olarak veya denetleyici başına veya eylem temelinde yapılandırılabilir. Razor Sayfalar uygulamalarında, bunlar genel olarak veya sayfa modeli başına yapılandırılabilir. Bu filtreler, bir denetleyici eyleminin veya başka bir filtrenin yürütülmesi sırasında oluşan işlenmeyen özel durumları işler. Daha fazla bilgi için bkz . ASP.NET Core'daki filtreler.

Özel durum filtreleri, MVC eylemleri içinde oluşan özel durumları yakalamak için kullanışlıdır, ancak yerleşik özel durum işleme ara yazılımıUseExceptionHandler kadar esnek değildir. Hangi MVC eyleminin seçildiğine göre farklı hata işleme gerçekleştirmeniz gerekmediği sürece kullanmanızı UseExceptionHandleröneririz.

Model durumu hataları

Model durumu hatalarını işleme hakkında bilgi için bkz . Model bağlama ve Model doğrulama.

Sorun ayrıntıları

Sorun Ayrıntıları , HTTP API hatasını açıklayan tek yanıt biçimi değildir, ancak genellikle HTTP API'lerine yönelik hataları bildirmek için kullanılır.

Sorun ayrıntıları hizmeti, ASP.NET Core'da sorun ayrıntıları oluşturmayı destekleyen arabirimini uygular IProblemDetailsService . AddProblemDetails üzerindeki IServiceCollection uzantı yöntemi, varsayılan IProblemDetailsService uygulamayı kaydeder.

ASP.NET Core uygulamalarında, istek HTTP üst bilgisinin kayıtlı tarafından desteklenen içerik türlerinden birini içermemesiAcceptdışında, aşağıdaki ara yazılım çağrıldığında AddProblemDetails sorun ayrıntıları HTTP yanıtları oluşturur (varsayılan: application/json):IProblemDetailsWriter

Aşağıdaki kod, uygulamayı henüz gövde içeriği olmayan tüm HTTP istemcisi ve sunucu hata yanıtları için bir sorun ayrıntıları yanıtı oluşturacak şekilde yapılandırır:

builder.Services.AddProblemDetails();

var app = builder.Build();        

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler();
    app.UseHsts();
}

app.UseStatusCodePages();

Sonraki bölümde sorun ayrıntıları yanıt gövdesinin nasıl özelleştirileceği gösterilmektedir.

Sorun ayrıntılarını özelleştirme

öğesinin ProblemDetails otomatik olarak oluşturulması, aşağıdaki seçeneklerden herhangi biri kullanılarak özelleştirilebilir:

  1. ProblemDetailsOptions.CustomizeProblemDetails komutunu kullanma
  2. Özel kullanım IProblemDetailsWriter
  3. ara yazılımda öğesini IProblemDetailsService çağırma

CustomizeProblemDetails Işlem

Oluşturulan sorun ayrıntıları kullanılarak CustomizeProblemDetailsözelleştirilebilir ve özelleştirmeler otomatik olarak oluşturulan tüm sorun ayrıntılarına uygulanır.

Ayarlamak için CustomizeProblemDetailsaşağıdaki kod kullanılırProblemDetailsOptions:

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

Örneğin, bir HTTP Status 400 Bad Request uç nokta sonucu aşağıdaki sorun ayrıntıları yanıt gövdesini oluşturur:

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "Bad Request",
  "status": 400,
  "nodeId": "my-machine-name"
}

Özel IProblemDetailsWriter

Gelişmiş özelleştirmeler için bir IProblemDetailsWriter uygulama oluşturulabilir.

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

Not: Özel IProblemDetailsWriterkullanılırken, özel IProblemDetailsWriter öğesinin , , AddControllersWithViewsAddControllersveya AddMvcçağrılmadan AddRazorPagesönce kaydedilmesi gerekir:

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

Ara Yazılımdan sorun ayrıntıları

ile CustomizeProblemDetails kullanmak ProblemDetailsOptions için alternatif bir yaklaşım, ara yazılımı ayarlamaktırProblemDetails. Bir sorun ayrıntıları yanıtı çağrılarak IProblemDetailsService.WriteAsyncyazılabilir:

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

Yukarıdaki kodda, en düşük API uç noktaları /divide ve /squareroot hata girişinde beklenen özel sorun yanıtını döndürür.

API denetleyicisi uç noktaları, özel sorun yanıtını değil hata girişinde varsayılan sorun yanıtını döndürür. API denetleyicisi yanıt akışına yazdığı için varsayılan sorun yanıtı döndürülür; hata durum kodları için sorun ayrıntıları, daha önce IProblemDetailsService.WriteAsync çağrılır ve yanıt yeniden yazılmaz .

Aşağıdaki ValuesController , yanıt akışına yazan ve bu nedenle özel sorun yanıtının döndürülmesini önleyen döndürür BadRequestResult.

[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şağıdaki Values3Controller , beklenen özel sorun sonucunun döndürülmesi için döndürür ControllerBase.Problem :

[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));
    }

}

Özel durumlar için ProblemDetails yükü oluşturma

Aşağıdaki uygulamayı göz önünde bulundurun:

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

Geliştirme dışı ortamlarda, bir özel durum oluştuğunda, istemciye döndürülen standart bir ProblemDetails yanıtı aşağıdadır:

{
"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"
}

Çoğu uygulama için, özel durumlar için gereken tek şey yukarıdaki koddur. Ancak aşağıdaki bölümde daha ayrıntılı sorun yanıtlarının nasıl alınıyor olduğu gösterilmektedir.

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak hataya erişim sağlar ve ile IProblemDetailsService.WriteAsyncbir sorun ayrıntıları yanıtı yazar:

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

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Sorun ayrıntıları oluşturmak için alternatif bir yaklaşım, özel durumları ve istemci hatalarını sorun ayrıntılarıyla eşlemek için kullanılabilecek üçüncü taraf NuGet paketini Hellang.Middleware.ProblemDetails kullanmaktır.

Ek kaynaklar

Tarafından Tom Dykstra

Bu makalede, ASP.NET Core web uygulamalarında hataları işlemeye yönelik yaygın yaklaşımlar ele alınıyor. Ayrıca bkz. ASP.NET Core web API'lerindeki hataları işleme ve Minimum API uygulamalarında hataları işleme.

Geliştirici özel durum sayfası

Geliştirici Özel Durum Sayfası, işlenmeyen istek özel durumları hakkında ayrıntılı bilgiler görüntüler. ASP.NET Core uygulamaları, her ikisi de aşağıdaki durumlarda varsayılan olarak geliştirici özel durum sayfasını etkinleştirir:

  • Geliştirme ortamında çalıştırılıyor.
  • Geçerli şablonlarla, yani WebApplication.CreateBuilder kullanılarak oluşturulan uygulama. kullanılarak oluşturulan uygulamalar, WebHost.CreateDefaultBuilder içinde Configurearayarak app.UseDeveloperExceptionPage geliştirici özel durum sayfasını etkinleştirmelidir.

Geliştirici özel durum sayfası ara yazılım işlem hattında erken çalıştırılır, böylece izleyen ara yazılımda işlenmeyen özel durumları yakalayabilir.

Uygulama Üretim ortamında çalıştırıldığında ayrıntılı özel durum bilgileri genel olarak görüntülenmemelidir. Ortamları yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma.

Geliştirici Özel Durum Sayfası, özel durum ve istek hakkında aşağıdaki bilgileri içerebilir:

  • Yığın izleme
  • Varsa sorgu dizesi parametreleri
  • Cookies, varsa
  • Üst Bilgiler

Geliştirici Özel Durum Sayfası'nın herhangi bir bilgi sağlaması garanti değildir. Tam hata bilgileri için Günlüğe Kaydetme özelliğini kullanın.

Özel durum işleyici sayfası

Üretim ortamı için özel bir hata işleme sayfası yapılandırmak için öğesini çağırınUseExceptionHandler. Ara yazılımı işleyen bu özel durum:

  • İşlenmeyen özel durumları yakalar ve günlüğe kaydeder.
  • Belirtilen yolu kullanarak isteği alternatif bir işlem hattında yeniden yürütür. Yanıt başlatıldıysa istek yeniden yürütülemez. Şablon tarafından oluşturulan kod, yolu kullanarak isteği yeniden yürütür /Error .

Uyarı

Alternatif işlem hattı kendi özel durumu oluşturursa, Özel Durum İşleme Ara Yazılımı özgün özel durumu yeniden oluşturur.

Bu ara yazılım istek işlem hattını yeniden yürütebileceğinden:

  • Ara yazılımların yeniden giriş işlemini aynı istekle işlemesi gerekir. Bu normalde, çağrısından _next sonra durumlarını temizleme veya işlemi yeniden yapmaktan kaçınmak için üzerindeki işlemlerini HttpContext önbelleğe alma anlamına gelir. İstek gövdesiyle ilgilenirken bu, Sonuçları Form okuyucusu gibi arabelleğe alma veya önbelleğe alma anlamına gelir.
  • UseExceptionHandler(IApplicationBuilder, String) Şablonlarda kullanılan aşırı yükleme için yalnızca istek yolu değiştirilir ve yol verileri temizlenir. Üst bilgiler, yöntem ve öğeler gibi istek verilerinin tümü olduğu gibi yeniden kullanılır.
  • Kapsamı belirlenmiş hizmetler aynı kalır.

Aşağıdaki örnekte, UseExceptionHandler Geliştirme dışı ortamlarda özel durum işleme ara yazılımını ekler:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Sayfalar uygulama şablonu, Razor Sayfalar klasöründe bir Hata sayfası (.cshtml) ve PageModel sınıf (ErrorModel) sağlar. Bir MVC uygulaması için proje şablonu, denetleyici için Home bir Error eylem yöntemi ve Hata görünümü içerir.

Özel durum işleme ara yazılımı özgün HTTP yöntemini kullanarak isteği yeniden yürütür. Hata işleyicisi uç noktası belirli bir HTTP yöntemleri kümesiyle sınırlıysa, yalnızca bu HTTP yöntemleri için çalışır. Örneğin, özniteliğini kullanan [HttpGet] bir MVC denetleyicisi eylemi yalnızca GET istekleri için çalıştırılır. Tüm isteklerin özel hata işleme sayfasına ulaştığından emin olmak için bunları belirli bir HTTP yöntemleri kümesiyle kısıtlamayın.

Özel durumları özgün HTTP yöntemine göre farklı şekilde işlemek için:

  • Sayfalar için Razor birden çok işleyici yöntemi oluşturun. Örneğin, GET özel durumlarını işlemek için kullanın OnGet ve POST özel durumlarını işlemek için kullanın OnPost .
  • MVC için, birden çok eyleme HTTP fiili öznitelikleri uygulayın. Örneğin, GET özel durumlarını işlemek için kullanın [HttpGet] ve POST özel durumlarını işlemek için kullanın [HttpPost] .

Kimliği doğrulanmamış kullanıcıların özel hata işleme sayfasını görüntülemesine izin vermek için anonim erişimi desteklediğinden emin olun.

Özel duruma erişme

Hata işleyicisinde özel duruma ve özgün istek yoluna erişmek için kullanın IExceptionHandlerPathFeature . Aşağıdaki örnek, oluşturulan özel durum hakkında daha fazla bilgi almak için kullanır IExceptionHandlerPathFeature :

[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.";
        }
    }
}

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Özel durum işleyici lambda

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak, yanıtı döndürmeden önce hataya erişim sağlar.

Aşağıdaki kod özel durum işleme için bir lambda kullanır:

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

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

IExceptionHandler

IExceptionHandler , geliştiriciye merkezi bir konumda bilinen özel durumları işlemek için geri çağırma sağlayan bir arabirimdir.

IExceptionHandler uygulamaları çağrılarak IServiceCollection.AddExceptionHandler<T>kaydedilir. Bir IExceptionHandler örneğin ömrü tekildir. Birden çok uygulama eklenebilir ve bunlar kayıtlı sırayla çağrılır.

Bir özel durum işleyicisi bir isteği işlerse, işlemeyi durdurmak için geri dönebilir true . Bir özel durum işleyicisi herhangi bir özel durum işleyicisi tarafından işlenmezse denetim, ara yazılımdaki varsayılan davranışa ve seçeneklere geri döner. İşlenen ve işlenmeyen özel durumlar için farklı ölçümler ve günlükler yayılır.

Aşağıdaki örnekte bir IExceptionHandler uygulama gösterilmektedir:

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

Aşağıdaki örnekte, bağımlılık ekleme için bir IExceptionHandler uygulamanın nasıl kaydedilecekleri gösterilmektedir:

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

Yukarıdaki kod Geliştirme ortamında çalıştırıldığında:

  • CustomExceptionHandler bir özel durumu işlemek için ilk olarak çağrılır.
  • Özel durumu günlüğe kaydettikten sonra yöntemi döndürürfalse, TryHandleException bu nedenle geliştirici özel durum sayfası gösterilir.

Diğer ortamlarda:

  • CustomExceptionHandler bir özel durumu işlemek için ilk olarak çağrılır.
  • Özel durumu TryHandleException günlüğe kaydettikten sonra yöntemi döndürür false, böylece /Error sayfa gösterilir.

UseStatusCodePages

Varsayılan olarak, ASP.NET Core uygulaması HTTP hata durum kodları için 404 - Bulunamadı gibi bir durum kodu sayfası sağlamaz. Uygulama gövdesi olmayan bir HTTP 400-599 hata durum kodu ayarladığında, durum kodunu ve boş bir yanıt gövdesini döndürür. Yaygın hata durum kodları için varsayılan yalnızca metin işleyicilerini etkinleştirmek için çağrısında UseStatusCodePages kullanın Program.cs:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages();

İstek işleme ara yazılımından önce çağırın UseStatusCodePages . Örneğin, Statik Dosya Ara Yazılımı ve Uç Noktalar Ara Yazılımı'nın önünde çağırın UseStatusCodePages .

Kullanılmadığında UseStatusCodePages , uç nokta olmadan URL'ye gitmek, uç noktanın bulunamadığını belirten tarayıcıya bağlı bir hata iletisi döndürür. Çağrıldığında UseStatusCodePages , tarayıcı aşağıdaki yanıtı döndürür:

Status Code: 404; Not Found

UseStatusCodePages genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

Not

Durum kodu sayfaları ara yazılımı özel durumları yakalamaz. Özel hata işleme sayfası sağlamak için özel durum işleyici sayfasını kullanın.

Biçim dizesi ile UseStatusCodePages

Yanıt içerik türünü ve metnini özelleştirmek için, bir içerik türü ve biçim dizesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

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}");

Yukarıdaki kodda, {0} hata kodu için bir yer tutucudur.

UseStatusCodePages kullanıcılar için yararlı olmayan bir ileti döndürdüğü için, biçim dizesi genellikle üretimde kullanılmaz.

Lambda ile UseStatusCodePages

Özel hata işleme ve yanıt yazma kodu belirtmek için bir lambda ifadesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages(async statusCodeContext =>
{
    // using static System.Net.Mime.MediaTypeNames;
    statusCodeContext.HttpContext.Response.ContentType = Text.Plain;

    await statusCodeContext.HttpContext.Response.WriteAsync(
        $"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});

UseStatusCodePages lambda ile genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects Uzantı yöntemi:

  • İstemciye bir 302 - Bulundu durum kodu gönderir.
  • İstemciyi URL şablonunda sağlanan hata işleme uç noktasına yönlendirir. Hata işleme uç noktası genellikle hata bilgilerini görüntüler ve HTTP 200 döndürür.
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");

URL şablonu, önceki kodda gösterildiği gibi durum kodu için bir {0} yer tutucu içerebilir. URL şablonu (tilde) ile ~ başlıyorsa, ~ yerine uygulamanın PathBaseolur. Uygulamada bir uç nokta belirtirken, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulama şu durumlarda kullanılır:

  • genellikle farklı bir uygulamanın hatayı işlediği durumlarda istemciyi farklı bir uç noktaya yönlendirmelidir. Web uygulamaları için istemcinin tarayıcı adres çubuğu yeniden yönlendirilen uç noktayı yansıtır.
  • İlk yeniden yönlendirme yanıtıyla özgün durum kodunu korumamalı ve döndürmemelidir.

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute Uzantı yöntemi:

  • Alternatif bir yol kullanarak istek işlem hattını yeniden yürüterek yanıt gövdesini oluşturur.
  • İşlem hattı yeniden yürütülmeden önce veya sonra durum kodunu değiştirmez.

Yeni işlem hattı, durum kodu üzerinde tam denetime sahip olduğundan yeni işlem hattı yürütmesi yanıtın durum kodunu değiştirebilir. Yeni işlem hattı durum kodunu değiştirmezse, özgün durum kodu istemciye gönderilir.

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");

Uygulama içinde bir uç nokta belirtilirse, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulamanın aşağıdakileri yapması gerektiğinde kullanılır:

  • İsteği farklı bir uç noktaya yeniden yönlendirmeden işleyin. Web uygulamaları için istemcinin tarayıcı adres çubuğu başlangıçta istenen uç noktayı yansıtır.
  • Yanıtla birlikte özgün durum kodunu koruyun ve döndürin.

URL şablonu ile / başlamalıdır ve durum kodu için bir yer tutucu {0} içerebilir. Durum kodunu sorgu dizesi parametresi olarak geçirmek için içine ikinci bir bağımsız değişken UseStatusCodePagesWithReExecutegeçirin. Örneğin:

var app = builder.Build();  
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");

Hatayı işleyen uç nokta, aşağıdaki örnekte gösterildiği gibi hatayı oluşturan özgün URL'yi alabilir:

[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);
        }
    }
}

Bu ara yazılım istek işlem hattını yeniden yürütebileceğinden:

  • Ara yazılımların yeniden giriş işlemini aynı istekle işlemesi gerekir. Bu normalde, çağrısından _next sonra durumlarını temizleme veya işlemi yeniden yapmaktan kaçınmak için üzerindeki işlemlerini HttpContext önbelleğe alma anlamına gelir. İstek gövdesiyle ilgilenirken bu, Sonuçları Form okuyucusu gibi arabelleğe alma veya önbelleğe alma anlamına gelir.
  • Kapsamı belirlenmiş hizmetler aynı kalır.

Durum kodu sayfalarını devre dışı bırakma

MVC denetleyicisinin veya eylem yönteminin durum kodu sayfalarını devre dışı bırakmak için [SkipStatusCodePages] özniteliğini kullanın.

Pages işleyici yönteminde veya MVC denetleyicisinde Razor belirli istekler için durum kodu sayfalarını devre dışı bırakmak için kullanın IStatusCodePagesFeature:

public void OnGet()
{
    var statusCodePagesFeature =
        HttpContext.Features.Get<IStatusCodePagesFeature>();

    if (statusCodePagesFeature is not null)
    {
        statusCodePagesFeature.Enabled = false;
    }
}

Özel durum işleme kodu

Özel durum işleme sayfalarındaki kod da özel durumlar oluşturabilir. Üretim hata sayfaları kapsamlı bir şekilde test edilmeli ve kendi özel durumlarının oluşmasını önlemek için ek özen gösterilmelidir.

Yanıt üst bilgileri

Yanıtın üst bilgileri gönderildikten sonra:

  • Uygulama yanıtın durum kodunu değiştiremez.
  • Özel durum sayfaları veya işleyicileri çalıştırılamaz. Yanıt tamamlanmalıdır veya bağlantı durdurulmalıdır.

Sunucu özel durum işleme

Bir uygulamadaki özel durum işleme mantığına ek olarak, HTTP sunucusu uygulaması bazı özel durumları işleyebilir. Sunucu yanıt üst bilgileri gönderilmeden önce bir özel durum yakalarsa, yanıt gövdesi olmadan bir 500 - Internal Server Error yanıt gönderir. Yanıt üst bilgileri gönderildikten sonra sunucu bir özel durum yakalarsa, sunucu bağlantıyı kapatır. Uygulama tarafından işlenmemiş istekler sunucu tarafından işlenir. Sunucu isteği işlerken oluşan özel durumlar, sunucunun özel durum işlemesi tarafından işlenir. Uygulamanın özel hata sayfaları, özel durum işleme ara yazılımı ve filtreler bu davranışı etkilemez.

Özel durum işlemeyi başlatma

Yalnızca barındırma katmanı, uygulama başlatma sırasında gerçekleşen özel durumları işleyebilir. Konak, başlangıç hatalarını yakalamak ve ayrıntılı hataları yakalamak için yapılandırılabilir.

Barındırma katmanı, yakalanan başlatma hatası için yalnızca ana bilgisayar adresi/bağlantı noktası bağlaması sonrasında hata oluşması durumunda bir hata sayfası gösterebilir. Bağlama başarısız olursa:

  • Barındırma katmanı kritik bir özel durumu günlüğe kaydeder.
  • dotnet işlemi kilitleniyor.
  • HTTP sunucusu olduğunda hiçbir hata sayfası görüntülenmez Kestrel.

IIS (veya Azure Uygulaması Hizmeti) veya IIS Express üzerinde çalışırken, işlem başlatılamıyorsa ASP.NET Çekirdek Modülü tarafından 502.5 - İşlem Hatası döndürülür. Daha fazla bilgi için bkz. Azure Uygulaması Hizmeti ve IIS'de ASP.NET Core sorunlarını giderme.

Veritabanı hata sayfası

Veritabanı geliştirici sayfası özel durum filtresi AddDatabaseDeveloperPageExceptionFilter , Entity Framework Core geçişleri kullanılarak çözümlenebilen veritabanıyla ilgili özel durumları yakalar. Bu özel durumlar oluştuğunda, sorunu çözmek için olası eylemlerin ayrıntılarıyla birlikte bir HTML yanıtı oluşturulur. Bu sayfa yalnızca Geliştirme ortamında etkinleştirilir. Aşağıdaki kod, Veritabanı geliştirici sayfası özel durum filtresini ekler:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();

Özel durum filtreleri

MVC uygulamalarında özel durum filtreleri genel olarak veya denetleyici başına veya eylem temelinde yapılandırılabilir. Razor Sayfalar uygulamalarında, bunlar genel olarak veya sayfa modeli başına yapılandırılabilir. Bu filtreler, bir denetleyici eyleminin veya başka bir filtrenin yürütülmesi sırasında oluşan işlenmeyen özel durumları işler. Daha fazla bilgi için bkz . ASP.NET Core'daki filtreler.

Özel durum filtreleri, MVC eylemleri içinde oluşan özel durumları yakalamak için kullanışlıdır, ancak yerleşik özel durum işleme ara yazılımıUseExceptionHandler kadar esnek değildir. Hangi MVC eyleminin seçildiğine göre farklı hata işleme gerçekleştirmeniz gerekmediği sürece kullanmanızı UseExceptionHandleröneririz.

Model durumu hataları

Model durumu hatalarını işleme hakkında bilgi için bkz . Model bağlama ve Model doğrulama.

Sorun ayrıntıları

Sorun Ayrıntıları , HTTP API hatasını açıklayan tek yanıt biçimi değildir, ancak genellikle HTTP API'lerine yönelik hataları bildirmek için kullanılır.

Sorun ayrıntıları hizmeti, ASP.NET Core'da sorun ayrıntıları oluşturmayı destekleyen arabirimini uygular IProblemDetailsService . AddProblemDetails üzerindeki IServiceCollection uzantı yöntemi, varsayılan IProblemDetailsService uygulamayı kaydeder.

ASP.NET Core uygulamalarında, istek HTTP üst bilgisinin kayıtlı tarafından desteklenen içerik türlerinden birini içermemesiAcceptdışında, aşağıdaki ara yazılım çağrıldığında AddProblemDetails sorun ayrıntıları HTTP yanıtları oluşturur (varsayılan: application/json):IProblemDetailsWriter

Aşağıdaki kod, uygulamayı henüz gövde içeriği olmayan tüm HTTP istemcisi ve sunucu hata yanıtları için bir sorun ayrıntıları yanıtı oluşturacak şekilde yapılandırır:

builder.Services.AddProblemDetails();

var app = builder.Build();        

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler();
    app.UseHsts();
}

app.UseStatusCodePages();

Sonraki bölümde sorun ayrıntıları yanıt gövdesinin nasıl özelleştirileceği gösterilmektedir.

Sorun ayrıntılarını özelleştirme

öğesinin ProblemDetails otomatik olarak oluşturulması, aşağıdaki seçeneklerden herhangi biri kullanılarak özelleştirilebilir:

  1. ProblemDetailsOptions.CustomizeProblemDetails komutunu kullanma
  2. Özel kullanım IProblemDetailsWriter
  3. ara yazılımda öğesini IProblemDetailsService çağırma

CustomizeProblemDetails Işlem

Oluşturulan sorun ayrıntıları kullanılarak CustomizeProblemDetailsözelleştirilebilir ve özelleştirmeler otomatik olarak oluşturulan tüm sorun ayrıntılarına uygulanır.

Ayarlamak için CustomizeProblemDetailsaşağıdaki kod kullanılırProblemDetailsOptions:

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

Örneğin, bir HTTP Status 400 Bad Request uç nokta sonucu aşağıdaki sorun ayrıntıları yanıt gövdesini oluşturur:

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "Bad Request",
  "status": 400,
  "nodeId": "my-machine-name"
}

Özel IProblemDetailsWriter

Gelişmiş özelleştirmeler için bir IProblemDetailsWriter uygulama oluşturulabilir.

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

Not: Özel IProblemDetailsWriterkullanılırken, özel IProblemDetailsWriter öğesinin , , AddControllersWithViewsAddControllersveya AddMvcçağrılmadan AddRazorPagesönce kaydedilmesi gerekir:

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

Ara Yazılımdan sorun ayrıntıları

ile CustomizeProblemDetails kullanmak ProblemDetailsOptions için alternatif bir yaklaşım, ara yazılımı ayarlamaktırProblemDetails. Bir sorun ayrıntıları yanıtı çağrılarak IProblemDetailsService.WriteAsyncyazılabilir:

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

Yukarıdaki kodda, en düşük API uç noktaları /divide ve /squareroot hata girişinde beklenen özel sorun yanıtını döndürür.

API denetleyicisi uç noktaları, özel sorun yanıtını değil hata girişinde varsayılan sorun yanıtını döndürür. API denetleyicisi yanıt akışına yazdığı için varsayılan sorun yanıtı döndürülür; hata durum kodları için sorun ayrıntıları, daha önce IProblemDetailsService.WriteAsync çağrılır ve yanıt yeniden yazılmaz .

Aşağıdaki ValuesController , yanıt akışına yazan ve bu nedenle özel sorun yanıtının döndürülmesini önleyen döndürür BadRequestResult.

[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şağıdaki Values3Controller , beklenen özel sorun sonucunun döndürülmesi için döndürür ControllerBase.Problem :

[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));
    }

}

Özel durumlar için ProblemDetails yükü oluşturma

Aşağıdaki uygulamayı göz önünde bulundurun:

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

Geliştirme dışı ortamlarda, bir özel durum oluştuğunda, istemciye döndürülen standart bir ProblemDetails yanıtı aşağıdadır:

{
"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"
}

Çoğu uygulama için, özel durumlar için gereken tek şey yukarıdaki koddur. Ancak aşağıdaki bölümde daha ayrıntılı sorun yanıtlarının nasıl alınıyor olduğu gösterilmektedir.

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak hataya erişim sağlar ve ile IProblemDetailsService.WriteAsyncbir sorun ayrıntıları yanıtı yazar:

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

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Sorun ayrıntıları oluşturmak için alternatif bir yaklaşım, özel durumları ve istemci hatalarını sorun ayrıntılarıyla eşlemek için kullanılabilecek üçüncü taraf NuGet paketini Hellang.Middleware.ProblemDetails kullanmaktır.

Ek kaynaklar

Tarafından Tom Dykstra

Bu makalede, ASP.NET Core web uygulamalarında hataları işlemeye yönelik yaygın yaklaşımlar ele alınıyor. Ayrıca bkz. ASP.NET Core web API'lerindeki hataları işleme ve Minimum API uygulamalarında hataları işleme.

Geliştirici özel durum sayfası

Geliştirici Özel Durum Sayfası, işlenmeyen istek özel durumları hakkında ayrıntılı bilgiler görüntüler. ASP.NET Core uygulamaları, her ikisi de aşağıdaki durumlarda varsayılan olarak geliştirici özel durum sayfasını etkinleştirir:

  • Geliştirme ortamında çalıştırılıyor.
  • Geçerli şablonlarla, yani WebApplication.CreateBuilder kullanılarak oluşturulan uygulama. kullanılarak oluşturulan uygulamalar, WebHost.CreateDefaultBuilder içinde Configurearayarak app.UseDeveloperExceptionPage geliştirici özel durum sayfasını etkinleştirmelidir.

Geliştirici özel durum sayfası ara yazılım işlem hattında erken çalıştırılır, böylece izleyen ara yazılımda işlenmeyen özel durumları yakalayabilir.

Uygulama Üretim ortamında çalıştırıldığında ayrıntılı özel durum bilgileri genel olarak görüntülenmemelidir. Ortamları yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma.

Geliştirici Özel Durum Sayfası, özel durum ve istek hakkında aşağıdaki bilgileri içerebilir:

  • Yığın izleme
  • Varsa sorgu dizesi parametreleri
  • Cookies, varsa
  • Üst Bilgiler

Geliştirici Özel Durum Sayfası'nın herhangi bir bilgi sağlaması garanti değildir. Tam hata bilgileri için Günlüğe Kaydetme özelliğini kullanın.

Özel durum işleyici sayfası

Üretim ortamı için özel bir hata işleme sayfası yapılandırmak için öğesini çağırınUseExceptionHandler. Ara yazılımı işleyen bu özel durum:

  • İşlenmeyen özel durumları yakalar ve günlüğe kaydeder.
  • Belirtilen yolu kullanarak isteği alternatif bir işlem hattında yeniden yürütür. Yanıt başlatıldıysa istek yeniden yürütülemez. Şablon tarafından oluşturulan kod, yolu kullanarak isteği yeniden yürütür /Error .

Uyarı

Alternatif işlem hattı kendi özel durumu oluşturursa, Özel Durum İşleme Ara Yazılımı özgün özel durumu yeniden oluşturur.

Bu ara yazılım istek işlem hattını yeniden yürütebileceğinden:

  • Ara yazılımların yeniden giriş işlemini aynı istekle işlemesi gerekir. Bu normalde, çağrısından _next sonra durumlarını temizleme veya işlemi yeniden yapmaktan kaçınmak için üzerindeki işlemlerini HttpContext önbelleğe alma anlamına gelir. İstek gövdesiyle ilgilenirken bu, Sonuçları Form okuyucusu gibi arabelleğe alma veya önbelleğe alma anlamına gelir.
  • UseExceptionHandler(IApplicationBuilder, String) Şablonlarda kullanılan aşırı yükleme için yalnızca istek yolu değiştirilir ve yol verileri temizlenir. Üst bilgiler, yöntem ve öğeler gibi istek verilerinin tümü olduğu gibi yeniden kullanılır.
  • Kapsamı belirlenmiş hizmetler aynı kalır.

Aşağıdaki örnekte, UseExceptionHandler Geliştirme dışı ortamlarda özel durum işleme ara yazılımını ekler:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Sayfalar uygulama şablonu, Razor Sayfalar klasöründe bir Hata sayfası (.cshtml) ve PageModel sınıf (ErrorModel) sağlar. Bir MVC uygulaması için proje şablonu, denetleyici için Home bir Error eylem yöntemi ve Hata görünümü içerir.

Özel durum işleme ara yazılımı özgün HTTP yöntemini kullanarak isteği yeniden yürütür. Hata işleyicisi uç noktası belirli bir HTTP yöntemleri kümesiyle sınırlıysa, yalnızca bu HTTP yöntemleri için çalışır. Örneğin, özniteliğini kullanan [HttpGet] bir MVC denetleyicisi eylemi yalnızca GET istekleri için çalıştırılır. Tüm isteklerin özel hata işleme sayfasına ulaştığından emin olmak için bunları belirli bir HTTP yöntemleri kümesiyle kısıtlamayın.

Özel durumları özgün HTTP yöntemine göre farklı şekilde işlemek için:

  • Sayfalar için Razor birden çok işleyici yöntemi oluşturun. Örneğin, GET özel durumlarını işlemek için kullanın OnGet ve POST özel durumlarını işlemek için kullanın OnPost .
  • MVC için, birden çok eyleme HTTP fiili öznitelikleri uygulayın. Örneğin, GET özel durumlarını işlemek için kullanın [HttpGet] ve POST özel durumlarını işlemek için kullanın [HttpPost] .

Kimliği doğrulanmamış kullanıcıların özel hata işleme sayfasını görüntülemesine izin vermek için anonim erişimi desteklediğinden emin olun.

Özel duruma erişme

Hata işleyicisinde özel duruma ve özgün istek yoluna erişmek için kullanın IExceptionHandlerPathFeature . Aşağıdaki örnek, oluşturulan özel durum hakkında daha fazla bilgi almak için kullanır IExceptionHandlerPathFeature :

[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.";
        }
    }
}

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Özel durum işleyici lambda

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak, yanıtı döndürmeden önce hataya erişim sağlar.

Aşağıdaki kod özel durum işleme için bir lambda kullanır:

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

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

UseStatusCodePages

Varsayılan olarak, ASP.NET Core uygulaması HTTP hata durum kodları için 404 - Bulunamadı gibi bir durum kodu sayfası sağlamaz. Uygulama gövdesi olmayan bir HTTP 400-599 hata durum kodu ayarladığında, durum kodunu ve boş bir yanıt gövdesini döndürür. Yaygın hata durum kodları için varsayılan yalnızca metin işleyicilerini etkinleştirmek için çağrısında UseStatusCodePages kullanın Program.cs:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages();

İstek işleme ara yazılımından önce çağırın UseStatusCodePages . Örneğin, Statik Dosya Ara Yazılımı ve Uç Noktalar Ara Yazılımı'nın önünde çağırın UseStatusCodePages .

Kullanılmadığında UseStatusCodePages , uç nokta olmadan URL'ye gitmek, uç noktanın bulunamadığını belirten tarayıcıya bağlı bir hata iletisi döndürür. Çağrıldığında UseStatusCodePages , tarayıcı aşağıdaki yanıtı döndürür:

Status Code: 404; Not Found

UseStatusCodePages genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

Not

Durum kodu sayfaları ara yazılımı özel durumları yakalamaz. Özel hata işleme sayfası sağlamak için özel durum işleyici sayfasını kullanın.

Biçim dizesi ile UseStatusCodePages

Yanıt içerik türünü ve metnini özelleştirmek için, bir içerik türü ve biçim dizesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

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}");

Yukarıdaki kodda, {0} hata kodu için bir yer tutucudur.

UseStatusCodePages kullanıcılar için yararlı olmayan bir ileti döndürdüğü için, biçim dizesi genellikle üretimde kullanılmaz.

Lambda ile UseStatusCodePages

Özel hata işleme ve yanıt yazma kodu belirtmek için bir lambda ifadesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages(async statusCodeContext =>
{
    // using static System.Net.Mime.MediaTypeNames;
    statusCodeContext.HttpContext.Response.ContentType = Text.Plain;

    await statusCodeContext.HttpContext.Response.WriteAsync(
        $"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});

UseStatusCodePages lambda ile genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects Uzantı yöntemi:

  • İstemciye bir 302 - Bulundu durum kodu gönderir.
  • İstemciyi URL şablonunda sağlanan hata işleme uç noktasına yönlendirir. Hata işleme uç noktası genellikle hata bilgilerini görüntüler ve HTTP 200 döndürür.
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");

URL şablonu, önceki kodda gösterildiği gibi durum kodu için bir {0} yer tutucu içerebilir. URL şablonu (tilde) ile ~ başlıyorsa, ~ yerine uygulamanın PathBaseolur. Uygulamada bir uç nokta belirtirken, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulama şu durumlarda kullanılır:

  • genellikle farklı bir uygulamanın hatayı işlediği durumlarda istemciyi farklı bir uç noktaya yönlendirmelidir. Web uygulamaları için istemcinin tarayıcı adres çubuğu yeniden yönlendirilen uç noktayı yansıtır.
  • İlk yeniden yönlendirme yanıtıyla özgün durum kodunu korumamalı ve döndürmemelidir.

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute Uzantı yöntemi:

  • Alternatif bir yol kullanarak istek işlem hattını yeniden yürüterek yanıt gövdesini oluşturur.
  • İşlem hattı yeniden yürütülmeden önce veya sonra durum kodunu değiştirmez.

Yeni işlem hattı, durum kodu üzerinde tam denetime sahip olduğundan yeni işlem hattı yürütmesi yanıtın durum kodunu değiştirebilir. Yeni işlem hattı durum kodunu değiştirmezse, özgün durum kodu istemciye gönderilir.

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");

Uygulama içinde bir uç nokta belirtilirse, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulamanın aşağıdakileri yapması gerektiğinde kullanılır:

  • İsteği farklı bir uç noktaya yeniden yönlendirmeden işleyin. Web uygulamaları için istemcinin tarayıcı adres çubuğu başlangıçta istenen uç noktayı yansıtır.
  • Yanıtla birlikte özgün durum kodunu koruyun ve döndürin.

URL şablonu ile / başlamalıdır ve durum kodu için bir yer tutucu {0} içerebilir. Durum kodunu sorgu dizesi parametresi olarak geçirmek için içine ikinci bir bağımsız değişken UseStatusCodePagesWithReExecutegeçirin. Örneğin:

var app = builder.Build();  
app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");

Hatayı işleyen uç nokta, aşağıdaki örnekte gösterildiği gibi hatayı oluşturan özgün URL'yi alabilir:

[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);
        }
    }
}

Bu ara yazılım istek işlem hattını yeniden yürütebileceğinden:

  • Ara yazılımların yeniden giriş işlemini aynı istekle işlemesi gerekir. Bu normalde, çağrısından _next sonra durumlarını temizleme veya işlemi yeniden yapmaktan kaçınmak için üzerindeki işlemlerini HttpContext önbelleğe alma anlamına gelir. İstek gövdesiyle ilgilenirken bu, Sonuçları Form okuyucusu gibi arabelleğe alma veya önbelleğe alma anlamına gelir.
  • Kapsamı belirlenmiş hizmetler aynı kalır.

Durum kodu sayfalarını devre dışı bırakma

MVC denetleyicisinin veya eylem yönteminin durum kodu sayfalarını devre dışı bırakmak için [SkipStatusCodePages] özniteliğini kullanın.

Pages işleyici yönteminde veya MVC denetleyicisinde Razor belirli istekler için durum kodu sayfalarını devre dışı bırakmak için kullanın IStatusCodePagesFeature:

public void OnGet()
{
    var statusCodePagesFeature =
        HttpContext.Features.Get<IStatusCodePagesFeature>();

    if (statusCodePagesFeature is not null)
    {
        statusCodePagesFeature.Enabled = false;
    }
}

Özel durum işleme kodu

Özel durum işleme sayfalarındaki kod da özel durumlar oluşturabilir. Üretim hata sayfaları kapsamlı bir şekilde test edilmeli ve kendi özel durumlarının oluşmasını önlemek için ek özen gösterilmelidir.

Yanıt üst bilgileri

Yanıtın üst bilgileri gönderildikten sonra:

  • Uygulama yanıtın durum kodunu değiştiremez.
  • Özel durum sayfaları veya işleyicileri çalıştırılamaz. Yanıt tamamlanmalıdır veya bağlantı durdurulmalıdır.

Sunucu özel durum işleme

Bir uygulamadaki özel durum işleme mantığına ek olarak, HTTP sunucusu uygulaması bazı özel durumları işleyebilir. Sunucu yanıt üst bilgileri gönderilmeden önce bir özel durum yakalarsa, yanıt gövdesi olmadan bir 500 - Internal Server Error yanıt gönderir. Yanıt üst bilgileri gönderildikten sonra sunucu bir özel durum yakalarsa, sunucu bağlantıyı kapatır. Uygulama tarafından işlenmemiş istekler sunucu tarafından işlenir. Sunucu isteği işlerken oluşan özel durumlar, sunucunun özel durum işlemesi tarafından işlenir. Uygulamanın özel hata sayfaları, özel durum işleme ara yazılımı ve filtreler bu davranışı etkilemez.

Özel durum işlemeyi başlatma

Yalnızca barındırma katmanı, uygulama başlatma sırasında gerçekleşen özel durumları işleyebilir. Konak, başlangıç hatalarını yakalamak ve ayrıntılı hataları yakalamak için yapılandırılabilir.

Barındırma katmanı, yakalanan başlatma hatası için yalnızca ana bilgisayar adresi/bağlantı noktası bağlaması sonrasında hata oluşması durumunda bir hata sayfası gösterebilir. Bağlama başarısız olursa:

  • Barındırma katmanı kritik bir özel durumu günlüğe kaydeder.
  • dotnet işlemi kilitleniyor.
  • HTTP sunucusu olduğunda hiçbir hata sayfası görüntülenmez Kestrel.

IIS (veya Azure Uygulaması Hizmeti) veya IIS Express üzerinde çalışırken, işlem başlatılamıyorsa ASP.NET Çekirdek Modülü tarafından 502.5 - İşlem Hatası döndürülür. Daha fazla bilgi için bkz. Azure Uygulaması Hizmeti ve IIS'de ASP.NET Core sorunlarını giderme.

Veritabanı hata sayfası

Veritabanı geliştirici sayfası özel durum filtresi AddDatabaseDeveloperPageExceptionFilter , Entity Framework Core geçişleri kullanılarak çözümlenebilen veritabanıyla ilgili özel durumları yakalar. Bu özel durumlar oluştuğunda, sorunu çözmek için olası eylemlerin ayrıntılarıyla birlikte bir HTML yanıtı oluşturulur. Bu sayfa yalnızca Geliştirme ortamında etkinleştirilir. Aşağıdaki kod, Veritabanı geliştirici sayfası özel durum filtresini ekler:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();

Özel durum filtreleri

MVC uygulamalarında özel durum filtreleri genel olarak veya denetleyici başına veya eylem temelinde yapılandırılabilir. Razor Sayfalar uygulamalarında, bunlar genel olarak veya sayfa modeli başına yapılandırılabilir. Bu filtreler, bir denetleyici eyleminin veya başka bir filtrenin yürütülmesi sırasında oluşan işlenmeyen özel durumları işler. Daha fazla bilgi için bkz . ASP.NET Core'daki filtreler.

Özel durum filtreleri, MVC eylemleri içinde oluşan özel durumları yakalamak için kullanışlıdır, ancak yerleşik özel durum işleme ara yazılımıUseExceptionHandler kadar esnek değildir. Hangi MVC eyleminin seçildiğine göre farklı hata işleme gerçekleştirmeniz gerekmediği sürece kullanmanızı UseExceptionHandleröneririz.

Model durumu hataları

Model durumu hatalarını işleme hakkında bilgi için bkz . Model bağlama ve Model doğrulama.

Sorun ayrıntıları

Sorun Ayrıntıları , HTTP API hatasını açıklayan tek yanıt biçimi değildir, ancak genellikle HTTP API'lerine yönelik hataları bildirmek için kullanılır.

Sorun ayrıntıları hizmeti, ASP.NET Core'da sorun ayrıntıları oluşturmayı destekleyen arabirimini uygular IProblemDetailsService . AddProblemDetails üzerindeki IServiceCollection uzantı yöntemi, varsayılan IProblemDetailsService uygulamayı kaydeder.

ASP.NET Core uygulamalarında, istek HTTP üst bilgisinin kayıtlı tarafından desteklenen içerik türlerinden birini içermemesiAcceptdışında, aşağıdaki ara yazılım çağrıldığında AddProblemDetails sorun ayrıntıları HTTP yanıtları oluşturur (varsayılan: application/json):IProblemDetailsWriter

Aşağıdaki kod, uygulamayı henüz gövde içeriği olmayan tüm HTTP istemcisi ve sunucu hata yanıtları için bir sorun ayrıntıları yanıtı oluşturacak şekilde yapılandırır:

builder.Services.AddProblemDetails();

var app = builder.Build();        

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler();
    app.UseHsts();
}

app.UseStatusCodePages();

Sonraki bölümde sorun ayrıntıları yanıt gövdesinin nasıl özelleştirileceği gösterilmektedir.

Sorun ayrıntılarını özelleştirme

öğesinin ProblemDetails otomatik olarak oluşturulması, aşağıdaki seçeneklerden herhangi biri kullanılarak özelleştirilebilir:

  1. ProblemDetailsOptions.CustomizeProblemDetails komutunu kullanma
  2. Özel kullanım IProblemDetailsWriter
  3. ara yazılımda öğesini IProblemDetailsService çağırma

CustomizeProblemDetails Işlem

Oluşturulan sorun ayrıntıları kullanılarak CustomizeProblemDetailsözelleştirilebilir ve özelleştirmeler otomatik olarak oluşturulan tüm sorun ayrıntılarına uygulanır.

Ayarlamak için CustomizeProblemDetailsaşağıdaki kod kullanılırProblemDetailsOptions:

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

Örneğin, bir HTTP Status 400 Bad Request uç nokta sonucu aşağıdaki sorun ayrıntıları yanıt gövdesini oluşturur:

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "Bad Request",
  "status": 400,
  "nodeId": "my-machine-name"
}

Özel IProblemDetailsWriter

Gelişmiş özelleştirmeler için bir IProblemDetailsWriter uygulama oluşturulabilir.

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

Not: Özel IProblemDetailsWriterkullanılırken, özel IProblemDetailsWriter öğesinin , , AddControllersWithViewsAddControllersveya AddMvcçağrılmadan AddRazorPagesönce kaydedilmesi gerekir:

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

Ara Yazılımdan sorun ayrıntıları

ile CustomizeProblemDetails kullanmak ProblemDetailsOptions için alternatif bir yaklaşım, ara yazılımı ayarlamaktırProblemDetails. Bir sorun ayrıntıları yanıtı çağrılarak IProblemDetailsService.WriteAsyncyazılabilir:

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

Yukarıdaki kodda, en düşük API uç noktaları /divide ve /squareroot hata girişinde beklenen özel sorun yanıtını döndürür.

API denetleyicisi uç noktaları, özel sorun yanıtını değil hata girişinde varsayılan sorun yanıtını döndürür. API denetleyicisi yanıt akışına yazdığı için varsayılan sorun yanıtı döndürülür; hata durum kodları için sorun ayrıntıları, daha önce IProblemDetailsService.WriteAsync çağrılır ve yanıt yeniden yazılmaz .

Aşağıdaki ValuesController , yanıt akışına yazan ve bu nedenle özel sorun yanıtının döndürülmesini önleyen döndürür BadRequestResult.

[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şağıdaki Values3Controller , beklenen özel sorun sonucunun döndürülmesi için döndürür ControllerBase.Problem :

[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));
    }

}

Özel durumlar için ProblemDetails yükü oluşturma

Aşağıdaki uygulamayı göz önünde bulundurun:

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

Geliştirme dışı ortamlarda, bir özel durum oluştuğunda, istemciye döndürülen standart bir ProblemDetails yanıtı aşağıdadır:

{
"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"
}

Çoğu uygulama için, özel durumlar için gereken tek şey yukarıdaki koddur. Ancak aşağıdaki bölümde daha ayrıntılı sorun yanıtlarının nasıl alınıyor olduğu gösterilmektedir.

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak hataya erişim sağlar ve ile IProblemDetailsService.WriteAsyncbir sorun ayrıntıları yanıtı yazar:

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

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Sorun ayrıntıları oluşturmak için alternatif bir yaklaşım, özel durumları ve istemci hatalarını sorun ayrıntılarıyla eşlemek için kullanılabilecek üçüncü taraf NuGet paketini Hellang.Middleware.ProblemDetails kullanmaktır.

Ek kaynaklar

Tarafından Tom Dykstra

Bu makalede, ASP.NET Core web uygulamalarında hataları işlemeye yönelik yaygın yaklaşımlar ele alınıyor. Bkz . Web API'leri için ASP.NET Core web API'lerindeki hataları işleme.

Geliştirici özel durum sayfası

Geliştirici Özel Durum Sayfası, işlenmeyen istek özel durumları hakkında ayrıntılı bilgiler görüntüler. ASP.NET Core uygulamaları, her ikisi de aşağıdaki durumlarda varsayılan olarak geliştirici özel durum sayfasını etkinleştirir:

  • Geliştirme ortamında çalıştırılıyor.
  • Geçerli şablonlarla, yani WebApplication.CreateBuilder kullanılarak oluşturulan uygulama. kullanılarak oluşturulan uygulamalar, WebHost.CreateDefaultBuilder içinde Configurearayarak app.UseDeveloperExceptionPage geliştirici özel durum sayfasını etkinleştirmelidir.

Geliştirici özel durum sayfası ara yazılım işlem hattında erken çalıştırılır, böylece izleyen ara yazılımda işlenmeyen özel durumları yakalayabilir.

Uygulama Üretim ortamında çalıştırıldığında ayrıntılı özel durum bilgileri genel olarak görüntülenmemelidir. Ortamları yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma.

Geliştirici Özel Durum Sayfası, özel durum ve istek hakkında aşağıdaki bilgileri içerebilir:

  • Yığın izleme
  • Varsa sorgu dizesi parametreleri
  • Cookies, varsa
  • Üst Bilgiler

Geliştirici Özel Durum Sayfası'nın herhangi bir bilgi sağlaması garanti değildir. Tam hata bilgileri için Günlüğe Kaydetme özelliğini kullanın.

Özel durum işleyici sayfası

Üretim ortamı için özel bir hata işleme sayfası yapılandırmak için öğesini çağırınUseExceptionHandler. Ara yazılımı işleyen bu özel durum:

  • İşlenmeyen özel durumları yakalar ve günlüğe kaydeder.
  • Belirtilen yolu kullanarak isteği alternatif bir işlem hattında yeniden yürütür. Yanıt başlatıldıysa istek yeniden yürütülemez. Şablon tarafından oluşturulan kod, yolu kullanarak isteği yeniden yürütür /Error .

Uyarı

Alternatif işlem hattı kendi özel durumu oluşturursa, Özel Durum İşleme Ara Yazılımı özgün özel durumu yeniden oluşturur.

Aşağıdaki örnekte, UseExceptionHandler Geliştirme dışı ortamlarda özel durum işleme ara yazılımını ekler:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Sayfalar uygulama şablonu, Razor Sayfalar klasöründe bir Hata sayfası (.cshtml) ve PageModel sınıf (ErrorModel) sağlar. Bir MVC uygulaması için proje şablonu, denetleyici için Home bir Error eylem yöntemi ve Hata görünümü içerir.

Özel durum işleme ara yazılımı özgün HTTP yöntemini kullanarak isteği yeniden yürütür. Hata işleyicisi uç noktası belirli bir HTTP yöntemleri kümesiyle sınırlıysa, yalnızca bu HTTP yöntemleri için çalışır. Örneğin, özniteliğini kullanan [HttpGet] bir MVC denetleyicisi eylemi yalnızca GET istekleri için çalıştırılır. Tüm isteklerin özel hata işleme sayfasına ulaştığından emin olmak için bunları belirli bir HTTP yöntemleri kümesiyle kısıtlamayın.

Özel durumları özgün HTTP yöntemine göre farklı şekilde işlemek için:

  • Sayfalar için Razor birden çok işleyici yöntemi oluşturun. Örneğin, GET özel durumlarını işlemek için kullanın OnGet ve POST özel durumlarını işlemek için kullanın OnPost .
  • MVC için, birden çok eyleme HTTP fiili öznitelikleri uygulayın. Örneğin, GET özel durumlarını işlemek için kullanın [HttpGet] ve POST özel durumlarını işlemek için kullanın [HttpPost] .

Kimliği doğrulanmamış kullanıcıların özel hata işleme sayfasını görüntülemesine izin vermek için anonim erişimi desteklediğinden emin olun.

Özel duruma erişme

Hata işleyicisinde özel duruma ve özgün istek yoluna erişmek için kullanın IExceptionHandlerPathFeature . Aşağıdaki örnek, oluşturulan özel durum hakkında daha fazla bilgi almak için kullanır IExceptionHandlerPathFeature :

[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.";
        }
    }
}

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Özel durum işleyici lambda

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak, yanıtı döndürmeden önce hataya erişim sağlar.

Aşağıdaki kod özel durum işleme için bir lambda kullanır:

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

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

UseStatusCodePages

Varsayılan olarak, ASP.NET Core uygulaması HTTP hata durum kodları için 404 - Bulunamadı gibi bir durum kodu sayfası sağlamaz. Uygulama gövdesi olmayan bir HTTP 400-599 hata durum kodu ayarladığında, durum kodunu ve boş bir yanıt gövdesini döndürür. Yaygın hata durum kodları için varsayılan yalnızca metin işleyicilerini etkinleştirmek için çağrısında UseStatusCodePages kullanın Program.cs:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages();

İstek işleme ara yazılımından önce çağırın UseStatusCodePages . Örneğin, Statik Dosya Ara Yazılımı ve Uç Noktalar Ara Yazılımı'nın önünde çağırın UseStatusCodePages .

Kullanılmadığında UseStatusCodePages , uç nokta olmadan URL'ye gitmek, uç noktanın bulunamadığını belirten tarayıcıya bağlı bir hata iletisi döndürür. Çağrıldığında UseStatusCodePages , tarayıcı aşağıdaki yanıtı döndürür:

Status Code: 404; Not Found

UseStatusCodePages genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

Not

Durum kodu sayfaları ara yazılımı özel durumları yakalamaz. Özel hata işleme sayfası sağlamak için özel durum işleyici sayfasını kullanın.

Biçim dizesi ile UseStatusCodePages

Yanıt içerik türünü ve metnini özelleştirmek için, bir içerik türü ve biçim dizesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

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}");

Yukarıdaki kodda, {0} hata kodu için bir yer tutucudur.

UseStatusCodePages kullanıcılar için yararlı olmayan bir ileti döndürdüğü için, biçim dizesi genellikle üretimde kullanılmaz.

Lambda ile UseStatusCodePages

Özel hata işleme ve yanıt yazma kodu belirtmek için bir lambda ifadesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePages(async statusCodeContext =>
{
    // using static System.Net.Mime.MediaTypeNames;
    statusCodeContext.HttpContext.Response.ContentType = Text.Plain;

    await statusCodeContext.HttpContext.Response.WriteAsync(
        $"Status Code Page: {statusCodeContext.HttpContext.Response.StatusCode}");
});

UseStatusCodePages lambda ile genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects Uzantı yöntemi:

  • İstemciye bir 302 - Bulundu durum kodu gönderir.
  • İstemciyi URL şablonunda sağlanan hata işleme uç noktasına yönlendirir. Hata işleme uç noktası genellikle hata bilgilerini görüntüler ve HTTP 200 döndürür.
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithRedirects("/StatusCode/{0}");

URL şablonu, önceki kodda gösterildiği gibi durum kodu için bir {0} yer tutucu içerebilir. URL şablonu (tilde) ile ~ başlıyorsa, ~ yerine uygulamanın PathBaseolur. Uygulamada bir uç nokta belirtirken, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulama şu durumlarda kullanılır:

  • genellikle farklı bir uygulamanın hatayı işlediği durumlarda istemciyi farklı bir uç noktaya yönlendirmelidir. Web uygulamaları için istemcinin tarayıcı adres çubuğu yeniden yönlendirilen uç noktayı yansıtır.
  • İlk yeniden yönlendirme yanıtıyla özgün durum kodunu korumamalı ve döndürmemelidir.

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute Uzantı yöntemi:

  • İstemciye özgün durum kodunu döndürür.
  • Alternatif bir yol kullanarak istek işlem hattını yeniden yürüterek yanıt gövdesini oluşturur.
var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseStatusCodePagesWithReExecute("/StatusCode/{0}");

Uygulama içinde bir uç nokta belirtilirse, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun.

Bu yöntem genellikle uygulamanın aşağıdakileri yapması gerektiğinde kullanılır:

  • İsteği farklı bir uç noktaya yeniden yönlendirmeden işleyin. Web uygulamaları için istemcinin tarayıcı adres çubuğu başlangıçta istenen uç noktayı yansıtır.
  • Yanıtla birlikte özgün durum kodunu koruyun ve döndürin.

URL şablonu ile / başlamalıdır ve durum kodu için bir yer tutucu {0} içerebilir. Durum kodunu sorgu dizesi parametresi olarak geçirmek için içine ikinci bir bağımsız değişken UseStatusCodePagesWithReExecutegeçirin. Örneğin:

app.UseStatusCodePagesWithReExecute("/StatusCode", "?statusCode={0}");

Hatayı işleyen uç nokta, aşağıdaki örnekte gösterildiği gibi hatayı oluşturan özgün URL'yi alabilir:

[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);
        }
    }
}

Durum kodu sayfalarını devre dışı bırakma

MVC denetleyicisinin veya eylem yönteminin durum kodu sayfalarını devre dışı bırakmak için [SkipStatusCodePages] özniteliğini kullanın.

Pages işleyici yönteminde veya MVC denetleyicisinde Razor belirli istekler için durum kodu sayfalarını devre dışı bırakmak için kullanın IStatusCodePagesFeature:

public void OnGet()
{
    var statusCodePagesFeature =
        HttpContext.Features.Get<IStatusCodePagesFeature>();

    if (statusCodePagesFeature is not null)
    {
        statusCodePagesFeature.Enabled = false;
    }
}

Özel durum işleme kodu

Özel durum işleme sayfalarındaki kod da özel durumlar oluşturabilir. Üretim hata sayfaları kapsamlı bir şekilde test edilmeli ve kendi özel durumlarının oluşmasını önlemek için ek özen gösterilmelidir.

Yanıt üst bilgileri

Yanıtın üst bilgileri gönderildikten sonra:

  • Uygulama yanıtın durum kodunu değiştiremez.
  • Özel durum sayfaları veya işleyicileri çalıştırılamaz. Yanıt tamamlanmalıdır veya bağlantı durdurulmalıdır.

Sunucu özel durum işleme

Bir uygulamadaki özel durum işleme mantığına ek olarak, HTTP sunucusu uygulaması bazı özel durumları işleyebilir. Sunucu yanıt üst bilgileri gönderilmeden önce bir özel durum yakalarsa, yanıt gövdesi olmadan bir 500 - Internal Server Error yanıt gönderir. Yanıt üst bilgileri gönderildikten sonra sunucu bir özel durum yakalarsa, sunucu bağlantıyı kapatır. Uygulama tarafından işlenmemiş istekler sunucu tarafından işlenir. Sunucu isteği işlerken oluşan özel durumlar, sunucunun özel durum işlemesi tarafından işlenir. Uygulamanın özel hata sayfaları, özel durum işleme ara yazılımı ve filtreler bu davranışı etkilemez.

Özel durum işlemeyi başlatma

Yalnızca barındırma katmanı, uygulama başlatma sırasında gerçekleşen özel durumları işleyebilir. Konak, başlangıç hatalarını yakalamak ve ayrıntılı hataları yakalamak için yapılandırılabilir.

Barındırma katmanı, yakalanan başlatma hatası için yalnızca ana bilgisayar adresi/bağlantı noktası bağlaması sonrasında hata oluşması durumunda bir hata sayfası gösterebilir. Bağlama başarısız olursa:

  • Barındırma katmanı kritik bir özel durumu günlüğe kaydeder.
  • dotnet işlemi kilitleniyor.
  • HTTP sunucusu olduğunda hiçbir hata sayfası görüntülenmez Kestrel.

IIS (veya Azure Uygulaması Hizmeti) veya IIS Express üzerinde çalışırken, işlem başlatılamıyorsa ASP.NET Çekirdek Modülü tarafından 502.5 - İşlem Hatası döndürülür. Daha fazla bilgi için bkz. Azure Uygulaması Hizmeti ve IIS'de ASP.NET Core sorunlarını giderme.

Veritabanı hata sayfası

Veritabanı geliştirici sayfası özel durum filtresi AddDatabaseDeveloperPageExceptionFilter , Entity Framework Core geçişleri kullanılarak çözümlenebilen veritabanıyla ilgili özel durumları yakalar. Bu özel durumlar oluştuğunda, sorunu çözmek için olası eylemlerin ayrıntılarıyla birlikte bir HTML yanıtı oluşturulur. Bu sayfa yalnızca Geliştirme ortamında etkinleştirilir. Aşağıdaki kod, Veritabanı geliştirici sayfası özel durum filtresini ekler:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddRazorPages();

Özel durum filtreleri

MVC uygulamalarında özel durum filtreleri genel olarak veya denetleyici başına veya eylem temelinde yapılandırılabilir. Razor Sayfalar uygulamalarında, bunlar genel olarak veya sayfa modeli başına yapılandırılabilir. Bu filtreler, bir denetleyici eyleminin veya başka bir filtrenin yürütülmesi sırasında oluşan işlenmeyen özel durumları işler. Daha fazla bilgi için bkz . ASP.NET Core'daki filtreler.

Özel durum filtreleri, MVC eylemleri içinde oluşan özel durumları yakalamak için kullanışlıdır, ancak yerleşik özel durum işleme ara yazılımıUseExceptionHandler kadar esnek değildir. Hangi MVC eyleminin seçildiğine göre farklı hata işleme gerçekleştirmeniz gerekmediği sürece kullanmanızı UseExceptionHandleröneririz.

Model durumu hataları

Model durumu hatalarını işleme hakkında bilgi için bkz . Model bağlama ve Model doğrulama.

Ek kaynaklar

Kirk Larkin, Tom Dykstra ve Steve Smith tarafından

Bu makalede, ASP.NET Core web uygulamalarında hataları işlemeye yönelik yaygın yaklaşımlar ele alınıyor. Bkz . Web API'leri için ASP.NET Core web API'lerindeki hataları işleme.

Örnek kodu görüntüleyin veya indirme. (nasıl indirilir.) F12 tarayıcı geliştirici araçlarının ağ sekmesi, örnek uygulamayı test ederken kullanışlıdır.

Geliştirici Özel Durum Sayfası

Geliştirici Özel Durum Sayfası, işlenmeyen istek özel durumları hakkında ayrıntılı bilgiler görüntüler. ASP.NET Core şablonları aşağıdaki kodu oluşturur:

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

Yukarıdaki vurgulanan kod, uygulama Geliştirme ortamında çalışırken geliştirici özel durum sayfasını etkinleştirir.

Şablonlar ara yazılım işlem hattının erken aşamalarına yerleştirerek UseDeveloperExceptionPage aşağıdaki ara yazılımda oluşan işlenmeyen özel durumları yakalayabilmesini sağlar.

Yukarıdaki kod, Geliştirici Özel Durum Sayfası'nı yalnızca uygulama Geliştirme ortamında çalıştığında etkinleştirir. Uygulama Üretim ortamında çalıştırıldığında ayrıntılı özel durum bilgileri genel olarak görüntülenmemelidir. Ortamları yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma.

Geliştirici Özel Durum Sayfası, özel durum ve istek hakkında aşağıdaki bilgileri içerebilir:

  • Yığın izleme
  • Varsa sorgu dizesi parametreleri
  • Cookievarsa s
  • Üst Bilgiler

Geliştirici Özel Durum Sayfası'nın herhangi bir bilgi sağlaması garanti değildir. Tam hata bilgileri için Günlüğe Kaydetme özelliğini kullanın.

Özel durum işleyici sayfası

Üretim ortamı için özel bir hata işleme sayfası yapılandırmak için öğesini çağırınUseExceptionHandler. Ara yazılımı işleyen bu özel durum:

  • İşlenmeyen özel durumları yakalar ve günlüğe kaydeder.
  • Belirtilen yolu kullanarak isteği alternatif bir işlem hattında yeniden yürütür. Yanıt başlatıldıysa istek yeniden yürütülemez. Şablon tarafından oluşturulan kod, yolu kullanarak isteği yeniden yürütür /Error .

Uyarı

Alternatif işlem hattı kendi özel durumu oluşturursa, Özel Durum İşleme Ara Yazılımı özgün özel durumu yeniden oluşturur.

Aşağıdaki örnekte, UseExceptionHandler Geliştirme dışı ortamlarda özel durum işleme ara yazılımını ekler:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Sayfalar uygulama şablonu, Razor Sayfalar klasöründe bir Hata sayfası (.cshtml) ve PageModel sınıf (ErrorModel) sağlar. Bir MVC uygulaması için proje şablonu, denetleyici için Home bir Error eylem yöntemi ve Hata görünümü içerir.

Özel durum işleme ara yazılımı özgün HTTP yöntemini kullanarak isteği yeniden yürütür. Hata işleyicisi uç noktası belirli bir HTTP yöntemleri kümesiyle sınırlıysa, yalnızca bu HTTP yöntemleri için çalışır. Örneğin, özniteliğini kullanan [HttpGet] bir MVC denetleyicisi eylemi yalnızca GET istekleri için çalıştırılır. Tüm isteklerin özel hata işleme sayfasına ulaştığından emin olmak için bunları belirli bir HTTP yöntemleri kümesiyle kısıtlamayın.

Özel durumları özgün HTTP yöntemine göre farklı şekilde işlemek için:

  • Sayfalar için Razor birden çok işleyici yöntemi oluşturun. Örneğin, GET özel durumlarını işlemek için kullanın OnGet ve POST özel durumlarını işlemek için kullanın OnPost .
  • MVC için, birden çok eyleme HTTP fiili öznitelikleri uygulayın. Örneğin, GET özel durumlarını işlemek için kullanın [HttpGet] ve POST özel durumlarını işlemek için kullanın [HttpPost] .

Kimliği doğrulanmamış kullanıcıların özel hata işleme sayfasını görüntülemesine izin vermek için anonim erişimi desteklediğinden emin olun.

Özel duruma erişme

Hata işleyicisinde özel duruma ve özgün istek yoluna erişmek için kullanın IExceptionHandlerPathFeature . Aşağıdaki kod, ASP.NET Core şablonları tarafından oluşturulan varsayılan Pages/Error.cshtml.cs değere eklenirExceptionMessage:

[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";
        }
    }
}

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Örnek uygulamada özel durumu test etmek için:

  • Ortamı üretim olarak ayarlayın.
  • içindeki Program.csaçıklamalarını webBuilder.UseStartup<Startup>(); kaldırın.
  • Giriş sayfasında Özel durum tetikle'yi seçin.

Özel durum işleyici lambda

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak, yanıtı döndürmeden önce hataya erişim sağlar.

Aşağıdaki kod özel durum işleme için bir lambda kullanır:

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

Uyarı

İstemcilerden veya istemcilere hassas hata bilgileri sağlamayınIExceptionHandlerFeature.IExceptionHandlerPathFeature Hata sunma bir güvenlik riskidir.

Örnek uygulamada lambda işleme özel durumunu test etmek için:

  • Ortamı üretim olarak ayarlayın.
  • içindeki Program.csaçıklamalarını webBuilder.UseStartup<StartupLambda>(); kaldırın.
  • Giriş sayfasında Özel durum tetikle'yi seçin.

UseStatusCodePages

Varsayılan olarak, ASP.NET Core uygulaması HTTP hata durum kodları için 404 - Bulunamadı gibi bir durum kodu sayfası sağlamaz. Uygulama gövdesi olmayan bir HTTP 400-599 hata durum kodu ayarladığında, durum kodunu ve boş bir yanıt gövdesini döndürür. Durum kodu sayfaları sağlamak için durum kodu sayfaları ara yazılımını kullanın. Yaygın hata durum kodları için varsayılan yalnızca metin işleyicilerini etkinleştirmek için yöntemini çağırın UseStatusCodePagesStartup.Configure :

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseStatusCodePages();

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

İstek işleme ara yazılımından önce çağırın UseStatusCodePages . Örneğin, Statik Dosya Ara Yazılımı ve Uç Noktalar Ara Yazılımı'nın önünde çağırın UseStatusCodePages .

Kullanılmadığında UseStatusCodePages , uç nokta olmadan URL'ye gitmek, uç noktanın bulunamadığını belirten tarayıcıya bağlı bir hata iletisi döndürür. Örneğin, adresine gitmek.Home/Privacy2 Çağrıldığında UseStatusCodePages tarayıcı şunu döndürür:

Status Code: 404; Not Found

UseStatusCodePages genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

Örnek uygulamada test UseStatusCodePagesetmek için:

  • Ortamı üretim olarak ayarlayın.
  • içindeki Program.csaçıklamalarını webBuilder.UseStartup<StartupUseStatusCodePages>(); kaldırın.
  • Giriş sayfasındaki bağlantıları seçin.

Not

Durum kodu sayfaları ara yazılımı özel durumları yakalamaz. Özel hata işleme sayfası sağlamak için özel durum işleyici sayfasını kullanın.

Biçim dizesi ile UseStatusCodePages

Yanıt içerik türünü ve metnini özelleştirmek için, bir içerik türü ve biçim dizesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

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

Yukarıdaki kodda, {0} hata kodu için bir yer tutucudur.

UseStatusCodePages kullanıcılar için yararlı olmayan bir ileti döndürdüğü için, biçim dizesi genellikle üretimde kullanılmaz.

Örnek uygulamada test UseStatusCodePages etmek için içindeki açıklamalarını webBuilder.UseStartup<StartupFormat>();Program.cskaldırın.

Lambda ile UseStatusCodePages

Özel hata işleme ve yanıt yazma kodu belirtmek için bir lambda ifadesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseStatusCodePages(async context =>
    {
        context.HttpContext.Response.ContentType = "text/plain";

        await context.HttpContext.Response.WriteAsync(
            "Status code page, status code: " +
            context.HttpContext.Response.StatusCode);
    });

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

UseStatusCodePages lambda ile genellikle üretimde kullanılmaz çünkü kullanıcılar için yararlı olmayan bir ileti döndürür.

Örnek uygulamada test UseStatusCodePages etmek için içindeki açıklamalarını webBuilder.UseStartup<StartupStatusLambda>();Program.cskaldırın.

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects Uzantı yöntemi:

  • İstemciye bir 302 - Bulundu durum kodu gönderir.
  • İstemciyi URL şablonunda sağlanan hata işleme uç noktasına yönlendirir. Hata işleme uç noktası genellikle hata bilgilerini görüntüler ve HTTP 200 döndürür.
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();
    });
}

URL şablonu, önceki kodda gösterildiği gibi durum kodu için bir {0} yer tutucu içerebilir. URL şablonu (tilde) ile ~ başlıyorsa, ~ yerine uygulamanın PathBaseolur. Uygulamada bir uç nokta belirtirken, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun. Razor Sayfalar örneği için örnek uygulamadaki Pages/MyStatusCode.cshtml dosyasına bakın.

Bu yöntem genellikle uygulama şu durumlarda kullanılır:

  • genellikle farklı bir uygulamanın hatayı işlediği durumlarda istemciyi farklı bir uç noktaya yönlendirmelidir. Web uygulamaları için istemcinin tarayıcı adres çubuğu yeniden yönlendirilen uç noktayı yansıtır.
  • İlk yeniden yönlendirme yanıtıyla özgün durum kodunu korumamalı ve döndürmemelidir.

Örnek uygulamada test UseStatusCodePages etmek için içindeki açıklamalarını webBuilder.UseStartup<StartupSCredirect>();Program.cskaldırın.

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute Uzantı yöntemi:

  • İstemciye özgün durum kodunu döndürür.
  • Alternatif bir yol kullanarak istek işlem hattını yeniden yürüterek yanıt gövdesini oluşturur.
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();
    });
}

Uygulama içinde bir uç nokta belirtilirse, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun. İsteğin durum sayfasına yeniden yönlendirilmesi için önce UseRouting yerleştirildiğinden emin olunUseStatusCodePagesWithReExecute. Razor Sayfalar örneği için örnek uygulamadaki Pages/MyStatusCode2.cshtml dosyasına bakın.

Bu yöntem genellikle uygulamanın aşağıdakileri yapması gerektiğinde kullanılır:

  • İsteği farklı bir uç noktaya yeniden yönlendirmeden işleyin. Web uygulamaları için istemcinin tarayıcı adres çubuğu başlangıçta istenen uç noktayı yansıtır.
  • Yanıtla birlikte özgün durum kodunu koruyun ve döndürin.

URL ve sorgu dizesi şablonları durum kodu için bir yer tutucu {0} içerebilir. URL şablonu ile /başlamalıdır.

Hatayı işleyen uç nokta, aşağıdaki örnekte gösterildiği gibi hatayı oluşturan özgün URL'yi alabilir:

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class MyStatusCode2Model : PageModel
{
    public string RequestId { get; set; }
    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);

    public string ErrorStatusCode { get; set; }

    public string OriginalURL { get; set; }
    public bool ShowOriginalURL => !string.IsNullOrEmpty(OriginalURL);

    public void OnGet(string code)
    {
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
        ErrorStatusCode = code;

        var statusCodeReExecuteFeature = HttpContext.Features.Get<
                                               IStatusCodeReExecuteFeature>();
        if (statusCodeReExecuteFeature != null)
        {
            OriginalURL =
                statusCodeReExecuteFeature.OriginalPathBase
                + statusCodeReExecuteFeature.OriginalPath
                + statusCodeReExecuteFeature.OriginalQueryString;
        }
    }
}

Razor Sayfalar örneği için örnek uygulamadaki Pages/MyStatusCode2.cshtml dosyasına bakın.

Örnek uygulamada test UseStatusCodePages etmek için içindeki açıklamalarını webBuilder.UseStartup<StartupSCreX>();Program.cskaldırın.

Durum kodu sayfalarını devre dışı bırakma

MVC denetleyicisinin veya eylem yönteminin durum kodu sayfalarını devre dışı bırakmak için [SkipStatusCodePages] özniteliğini kullanın.

Pages işleyici yönteminde veya MVC denetleyicisinde Razor belirli istekler için durum kodu sayfalarını devre dışı bırakmak için kullanın IStatusCodePagesFeature:

public void OnGet()
{
    // using Microsoft.AspNetCore.Diagnostics;
    var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();

    if (statusCodePagesFeature != null)
    {
        statusCodePagesFeature.Enabled = false;
    }
}

Özel durum işleme kodu

Özel durum işleme sayfalarındaki kod da özel durumlar oluşturabilir. Üretim hata sayfaları kapsamlı bir şekilde test edilmeli ve kendi özel durumlarının oluşmasını önlemek için ek özen gösterilmelidir.

Yanıt üst bilgileri

Yanıtın üst bilgileri gönderildikten sonra:

  • Uygulama yanıtın durum kodunu değiştiremez.
  • Özel durum sayfaları veya işleyicileri çalıştırılamaz. Yanıt tamamlanmalıdır veya bağlantı durdurulmalıdır.

Sunucu özel durum işleme

Bir uygulamadaki özel durum işleme mantığına ek olarak, HTTP sunucusu uygulaması bazı özel durumları işleyebilir. Sunucu yanıt üst bilgileri gönderilmeden önce bir özel durum yakalarsa, yanıt gövdesi olmadan bir 500 - Internal Server Error yanıt gönderir. Yanıt üst bilgileri gönderildikten sonra sunucu bir özel durum yakalarsa, sunucu bağlantıyı kapatır. Uygulama tarafından işlenmemiş istekler sunucu tarafından işlenir. Sunucu isteği işlerken oluşan özel durumlar, sunucunun özel durum işlemesi tarafından işlenir. Uygulamanın özel hata sayfaları, özel durum işleme ara yazılımı ve filtreler bu davranışı etkilemez.

Özel durum işlemeyi başlatma

Yalnızca barındırma katmanı, uygulama başlatma sırasında gerçekleşen özel durumları işleyebilir. Konak, başlangıç hatalarını yakalamak ve ayrıntılı hataları yakalamak için yapılandırılabilir.

Barındırma katmanı, yakalanan başlatma hatası için yalnızca ana bilgisayar adresi/bağlantı noktası bağlaması sonrasında hata oluşması durumunda bir hata sayfası gösterebilir. Bağlama başarısız olursa:

  • Barındırma katmanı kritik bir özel durumu günlüğe kaydeder.
  • dotnet işlemi kilitleniyor.
  • HTTP sunucusu olduğunda hiçbir hata sayfası görüntülenmez Kestrel.

IIS (veya Azure Uygulaması Hizmeti) veya IIS Express üzerinde çalışırken, işlem başlatılamıyorsa ASP.NET Çekirdek Modülü tarafından 502.5 - İşlem Hatası döndürülür. Daha fazla bilgi için bkz. Azure Uygulaması Hizmeti ve IIS'de ASP.NET Core sorunlarını giderme.

Veritabanı hata sayfası

Veritabanı geliştirici sayfası özel durum filtresi AddDatabaseDeveloperPageExceptionFilter , Entity Framework Core geçişleri kullanılarak çözümlenebilen veritabanıyla ilgili özel durumları yakalar. Bu özel durumlar oluştuğunda, sorunu çözmek için olası eylemlerin ayrıntılarıyla birlikte bir HTML yanıtı oluşturulur. Bu sayfa yalnızca Geliştirme ortamında etkinleştirilir. Tek tek kullanıcı hesapları belirtildiğinde, ASP.NET Temel Razor Sayfalar şablonları tarafından aşağıdaki kod oluşturuldu:

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

Özel durum filtreleri

MVC uygulamalarında özel durum filtreleri genel olarak veya denetleyici başına veya eylem temelinde yapılandırılabilir. Razor Sayfalar uygulamalarında, bunlar genel olarak veya sayfa modeli başına yapılandırılabilir. Bu filtreler, bir denetleyici eyleminin veya başka bir filtrenin yürütülmesi sırasında oluşan işlenmeyen özel durumları işler. Daha fazla bilgi için bkz . ASP.NET Core'daki filtreler.

Özel durum filtreleri, MVC eylemleri içinde oluşan özel durumları yakalamak için kullanışlıdır, ancak yerleşik özel durum işleme ara yazılımıUseExceptionHandler kadar esnek değildir. Hangi MVC eyleminin seçildiğine göre farklı hata işleme gerçekleştirmeniz gerekmediği sürece kullanmanızı UseExceptionHandleröneririz.

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

Model durumu hataları

Model durumu hatalarını işleme hakkında bilgi için bkz . Model bağlama ve Model doğrulama.

Ek kaynaklar

Tarafından Tom Dykstra ve Steve Smith

Bu makalede, ASP.NET Core web uygulamalarında hataları işlemeye yönelik yaygın yaklaşımlar ele alınıyor. Bkz . Web API'leri için ASP.NET Core web API'lerindeki hataları işleme.

Örnek kodu görüntüleyin veya indirme. (nasıl indirilir.)

Geliştirici Özel Durum Sayfası

Geliştirici Özel Durum Sayfası, istek özel durumları hakkında ayrıntılı bilgiler görüntüler. ASP.NET Core şablonları aşağıdaki kodu oluşturur:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Yukarıdaki kod, uygulama Geliştirme ortamında çalışırken geliştirici özel durum sayfasını etkinleştirir.

Şablonlar herhangi bir ara yazılımdan önce yerleştirildiğinden UseDeveloperExceptionPage , aşağıdaki ara yazılımda özel durumlar yakalanmış olur.

Yukarıdaki kod, Geliştirici Özel Durum Sayfası'nı yalnızca uygulama Geliştirme ortamında çalışırken etkinleştirir. Uygulama üretimde çalıştırıldığında ayrıntılı özel durum bilgileri genel olarak görüntülenmemelidir. Ortamları yapılandırma hakkında daha fazla bilgi için bkz . ASP.NET Core'da birden çok ortam kullanma.

Geliştirici Özel Durum Sayfası, özel durum ve istek hakkında aşağıdaki bilgileri içerir:

  • Yığın izleme
  • Varsa sorgu dizesi parametreleri
  • Cookievarsa s
  • Üst Bilgiler

Özel durum işleyici sayfası

Üretim ortamı için özel hata işleme sayfası yapılandırmak için Özel Durum İşleme Ara Yazılımını kullanın. Ara yazılım:

  • Özel durumları yakalar ve günlüğe kaydeder.
  • Belirtilen sayfa veya denetleyici için isteği alternatif bir işlem hattında yeniden yürütür. Yanıt başlatıldıysa istek yeniden yürütülemez. Şablon tarafından oluşturulan kod isteği /Erroriçin yeniden yürütür.

Aşağıdaki örnekte, UseExceptionHandler Geliştirme dışı ortamlarda Özel Durum İşleme Ara Yazılımını ekler:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Sayfalar uygulama şablonu, Razor Sayfalar klasöründe bir Hata sayfası (.cshtml) ve PageModel sınıf (ErrorModel) sağlar. Bir MVC uygulaması için proje şablonu, denetleyicide Home bir Hata eylem yöntemi ve Hata görünümü içerir.

Hata işleyicisi eylem yöntemini gibi HttpGetHTTP yöntemi öznitelikleriyle işaretlemeyin. Açık fiiller, bazı isteklerin yöntemine ulaşmasını engeller. Kimliği doğrulanmamış kullanıcıların hata görünümünü görmesi gerekiyorsa yönteme anonim erişime izin verin.

Özel duruma erişme

Hata işleyici denetleyicisinde veya sayfasında özel duruma ve özgün istek yoluna erişmek için kullanın IExceptionHandlerPathFeature :

[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";
        }
    }
}

Uyarı

Hassas hata bilgilerini istemcilere sunma. Hata sunma bir güvenlik riskidir.

Önceki özel durum işleme sayfasını tetikleme için ortamı üretimler olarak ayarlayın ve bir özel durum zorlaması gerçekleştirin.

Özel durum işleyici lambda

Özel özel durum işleyici sayfasının alternatifi, öğesine UseExceptionHandlerbir lambda sağlamaktır. Lambda kullanmak, yanıtı döndürmeden önce hataya erişim sağlar.

Özel durum işleme için lambda kullanma örneği aşağıda verilmişti:

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

Yukarıdaki koda, await context.Response.WriteAsync(new string(' ', 512)); Internet Explorer tarayıcısının IE hata iletisi yerine hata iletisini görüntülemesi için eklenir. Daha fazla bilgi için bu GitHub konusuna bakın.

Uyarı

İstemcilerden veya istemcilere hassas hata bilgileri sağlamayınIExceptionHandlerFeature.IExceptionHandlerPathFeature Hata sunma bir güvenlik riskidir.

Örnek uygulamada özel durum işleme lambdasının sonucunu görmek için ve ErrorHandlerLambda önişlemci yönergelerini ProdEnvironment kullanın ve giriş sayfasında Özel durum tetikle'yi seçin.

UseStatusCodePages

Varsayılan olarak, ASP.NET Core uygulaması HTTP durum kodları için 404 - Bulunamadı gibi bir durum kodu sayfası sağlamaz. Uygulama bir durum kodu ve boş bir yanıt gövdesi döndürür. Durum kodu sayfaları sağlamak için Durum Kodu Sayfaları ara yazılımını kullanın.

Ara yazılım, Microsoft.AspNetCore.Diagnostics paketi tarafından kullanılabilir hale getirilir.

Yaygın hata durum kodları için varsayılan yalnızca metin işleyicilerini etkinleştirmek için yöntemini çağırın UseStatusCodePagesStartup.Configure :

app.UseStatusCodePages();

İstek işleme ara yazılımından önce çağrı UseStatusCodePages (örneğin, Statik Dosya Ara Yazılımı ve MVC Ara Yazılımı).

Kullanılmadığında UseStatusCodePages , uç nokta olmadan BIR URL'ye gitmek, uç noktanın bulunamadığını belirten tarayıcıya bağımlı bir hata iletisi döndürür. Örneğin, adresine gitmek.Home/Privacy2 Çağrıldığında UseStatusCodePages tarayıcı şunu döndürür:

Status Code: 404; Not Found

Biçim dizesi ile UseStatusCodePages

Yanıt içerik türünü ve metnini özelleştirmek için, bir içerik türü ve biçim dizesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

app.UseStatusCodePages(
    "text/plain", "Status code page, status code: {0}");

Lambda ile UseStatusCodePages

Özel hata işleme ve yanıt yazma kodu belirtmek için bir lambda ifadesi alan öğesinin aşırı yüklemesini UseStatusCodePages kullanın:

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

UseStatusCodePagesWithRedirects Uzantı yöntemi:

  • İstemciye bir 302 - Bulundu durum kodu gönderir.
  • İstemciyi URL şablonunda sağlanan konuma yönlendirir.
app.UseStatusCodePagesWithRedirects("/StatusCode?code={0}");

URL şablonu, örnekte gösterildiği gibi durum kodu için bir {0} yer tutucu içerebilir. URL şablonu (tilde) ile ~ başlıyorsa, ~ yerine uygulamanın PathBaseolur. Uygulama içindeki bir uç noktaya işaret ederseniz, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun. Razor Sayfalar örneği için örnek uygulamada bölümüne bakın Pages/StatusCode.cshtml.

Bu yöntem genellikle uygulama şu durumlarda kullanılır:

  • genellikle farklı bir uygulamanın hatayı işlediği durumlarda istemciyi farklı bir uç noktaya yönlendirmelidir. Web uygulamaları için istemcinin tarayıcı adres çubuğu yeniden yönlendirilen uç noktayı yansıtır.
  • İlk yeniden yönlendirme yanıtıyla özgün durum kodunu korumamalı ve döndürmemelidir.

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute Uzantı yöntemi:

  • İstemciye özgün durum kodunu döndürür.
  • Alternatif bir yol kullanarak istek işlem hattını yeniden yürüterek yanıt gövdesini oluşturur.
app.UseStatusCodePagesWithReExecute("/StatusCode","?code={0}");

Uygulama içindeki bir uç noktaya işaret ederseniz, uç nokta için bir MVC görünümü veya Razor sayfası oluşturun. İsteğin durum sayfasına yeniden yönlendirilmesi için önce UseRouting yerleştirildiğinden emin olunUseStatusCodePagesWithReExecute. Razor Sayfalar örneği için örnek uygulamada bölümüne bakın Pages/StatusCode.cshtml.

Bu yöntem genellikle uygulamanın aşağıdakileri yapması gerektiğinde kullanılır:

  • İsteği farklı bir uç noktaya yeniden yönlendirmeden işleyin. Web uygulamaları için istemcinin tarayıcı adres çubuğu başlangıçta istenen uç noktayı yansıtır.
  • Yanıtla birlikte özgün durum kodunu koruyun ve döndürin.

URL ve sorgu dizesi şablonları durum kodu için bir yer tutucu ({0}) içerebilir. URL şablonunun eğik çizgiyle (/ ) başlaması gerekir. Yolda yer tutucu kullanırken uç noktanın (sayfa veya denetleyici) yol kesimini işleyebildiğini onaylayın. Örneğin, hatalar için Bir Razor Sayfa isteğe bağlı yol kesim değerini şu yönergeyle @page kabul etmelidir:

@page "{code?}"

Hatayı işleyen uç nokta, aşağıdaki örnekte gösterildiği gibi hatayı oluşturan özgün URL'yi alabilir:

var statusCodeReExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature != null)
{
    OriginalURL =
        statusCodeReExecuteFeature.OriginalPathBase
        + statusCodeReExecuteFeature.OriginalPath
        + statusCodeReExecuteFeature.OriginalQueryString;
}

Hata işleyicisi eylem yöntemini gibi HttpGetHTTP yöntemi öznitelikleriyle işaretlemeyin. Açık fiiller, bazı isteklerin yöntemine ulaşmasını engeller. Kimliği doğrulanmamış kullanıcıların hata görünümünü görmesi gerekiyorsa yönteme anonim erişime izin verin.

Durum kodu sayfalarını devre dışı bırakma

MVC denetleyicisinin veya eylem yönteminin durum kodu sayfalarını devre dışı bırakmak için özniteliğini [SkipStatusCodePages] kullanın.

Pages işleyici yönteminde veya MVC denetleyicisinde Razor belirli istekler için durum kodu sayfalarını devre dışı bırakmak için kullanın IStatusCodePagesFeature:

var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();

if (statusCodePagesFeature != null)
{
    statusCodePagesFeature.Enabled = false;
}

Özel durum işleme kodu

Özel durum işleme sayfalarındaki kod özel durumlar oluşturabilir. Genellikle üretim hata sayfalarının tamamen statik içeriklerden oluşması iyi bir fikirdir.

Yanıt üst bilgileri

Yanıtın üst bilgileri gönderildikten sonra:

  • Uygulama yanıtın durum kodunu değiştiremez.
  • Özel durum sayfaları veya işleyicileri çalıştırılamaz. Yanıt tamamlanmalıdır veya bağlantı durdurulmalıdır.

Sunucu özel durum işleme

Uygulamanızdaki özel durum işleme mantığına ek olarak, HTTP sunucusu uygulaması bazı özel durumları işleyebilir. Yanıt üst bilgileri gönderilmeden önce sunucu bir özel durum yakalarsa, sunucu yanıt gövdesi olmadan 500 - İç Sunucu Hatası yanıtı gönderir. Yanıt üst bilgileri gönderildikten sonra sunucu bir özel durum yakalarsa, sunucu bağlantıyı kapatır. Uygulamanız tarafından işlenmemiş istekler sunucu tarafından işlenir. Sunucu isteği işlerken oluşan özel durumlar, sunucunun özel durum işlemesi tarafından işlenir. Uygulamanın özel hata sayfaları, özel durum işleme ara yazılımı ve filtreler bu davranışı etkilemez.

Özel durum işlemeyi başlatma

Yalnızca barındırma katmanı, uygulama başlatma sırasında gerçekleşen özel durumları işleyebilir. Konak, başlangıç hatalarını yakalamak ve ayrıntılı hataları yakalamak için yapılandırılabilir.

Barındırma katmanı, yakalanan başlatma hatası için yalnızca ana bilgisayar adresi/bağlantı noktası bağlaması sonrasında hata oluşması durumunda bir hata sayfası gösterebilir. Bağlama başarısız olursa:

  • Barındırma katmanı kritik bir özel durumu günlüğe kaydeder.
  • dotnet işlemi kilitleniyor.
  • HTTP sunucusu olduğunda hiçbir hata sayfası görüntülenmez Kestrel.

IIS (veya Azure Uygulaması Hizmeti) veya IIS Express üzerinde çalışırken, işlem başlatılamıyorsa ASP.NET Çekirdek Modülü tarafından 502.5 - İşlem Hatası döndürülür. Daha fazla bilgi için bkz. Azure Uygulaması Hizmeti ve IIS'de ASP.NET Core sorunlarını giderme.

Veritabanı hata sayfası

Veritabanı Hata Sayfası Ara Yazılımı, Entity Framework geçişleri kullanılarak çözümlenebilen veritabanıyla ilgili özel durumları yakalar. Bu özel durumlar oluştuğunda, sorunu çözmek için olası eylemlerin ayrıntılarını içeren bir HTML yanıtı oluşturulur. Bu sayfa yalnızca Geliştirme ortamında etkinleştirilmelidir. sayfasına kod ekleyerek sayfayı Startup.Configureetkinleştirin:

if (env.IsDevelopment())
{
    app.UseDatabaseErrorPage();
}

UseDatabaseErrorPageMicrosoft.AspNetCore.Diagnostics.EntityFrameworkCore NuGet paketini gerektirir.

Özel durum filtreleri

MVC uygulamalarında özel durum filtreleri genel olarak veya denetleyici başına veya eylem temelinde yapılandırılabilir. Razor Sayfalar uygulamalarında, bunlar genel olarak veya sayfa modeli başına yapılandırılabilir. Bu filtreler, bir denetleyici eyleminin veya başka bir filtrenin yürütülmesi sırasında oluşan işlenmeyen özel durumları işler. Daha fazla bilgi için bkz . ASP.NET Core'daki filtreler.

İpucu

Özel durum filtreleri, MVC eylemleri içinde oluşan özel durumları yakalamak için kullanışlıdır, ancak Özel Durum İşleme Ara Yazılımı kadar esnek değildir. Ara yazılımı kullanmanızı öneririz. Filtreleri yalnızca hangi MVC eyleminin seçildiğine göre farklı hata işleme gerçekleştirmeniz gerektiğinde kullanın.

Model durumu hataları

Model durumu hatalarını işleme hakkında bilgi için bkz . Model bağlama ve Model doğrulama.

Ek kaynaklar