ASP.NET Core Web API'lerde 500 İç Sunucu Hatası Nasıl Ele Alınır?

ASP.NET Core'da 500 hataları: Neden varsayılan yetersiz, kasıtlı 500 döndürme yöntemleri, global hata yönetimi ve hata ayıklama/günlükleme ipuçları.

Efe Demir

Efe Demir

27 April 2025

ASP.NET Core Web API'lerde 500 İç Sunucu Hatası Nasıl Ele Alınır?

Korkulan HTTP 500 Internal Server Error, sunucuda bir şeylerin ters gittiğine dair genel bir sinyaldir, ancak sunucu tam olarak sorun hakkında daha spesifik olamaz. ASP.NET Core Web API'leri geliştiren geliştiriciler için, bu hatalarla karşılaşmak ve bunları düzgün bir şekilde ele almak, sağlam, bakımı yapılabilir ve kullanıcı dostu uygulamalar oluşturmak için çok önemlidir. Çerçeve varsayılan mekanizmalar sağlarken, 500 hataları için yanıtı nasıl yakalayacağınızı, günlüğe kaydedeceğinizi ve özelleştireceğinizi anlamak esastır. Bu makale, varsayılan işlemenin yeterli olmayabileceği, 500 durum kodlarını kasıtlı olarak döndürmenin çeşitli yöntemleri, genel özel durum işleme stratejileri ve hata ayıklama ve günlüğe kaydetme için en iyi uygulamaları keşfederek ASP.NET Core içindeki 500 hatalarının nüanslarına inmektedir.

💡
Harika bir API Dokümantasyonu oluşturan harika bir API Test aracı mı istiyorsunuz? Güzel API Dokümantasyonu?

Geliştirici Ekibinizin maksimum verimlilikle birlikte çalışması için entegre, Hepsi Bir Arada bir platform mu istiyorsunuz?

Apidog tüm taleplerinizi karşılıyor ve Postman'in yerini çok daha uygun bir fiyata alıyor!
button

500 Internal Server Error Nedir?

HTTP standardı tarafından tanımlanan 500 durum kodu, sunucunun isteği yerine getirmesini engelleyen beklenmedik bir durumla karşılaştığını gösterir. Bu, bir istemci isteğiyle (genellikle 4xx hatasıyla sonuçlanacak hatalı bir istek gibi) değil, sunucunun görünüşte geçerli bir isteği işleme yeteneğiyle ilgili bir sunucu tarafı hatasıdır.

Bir ASP.NET Core uygulamasında, bu genellikle istek işleme hattı sırasında bir yerde (middleware, denetleyici eylemleri, hizmet sınıfları veya veri erişim katmanları içinde) meydana gelen işlenmemiş bir özel duruma dönüşür.

Neden Sadece Çerçevenin Halletmesine İzin Vermiyorsunuz?

ASP.NET Core, işlenmemiş özel durumları yakalamak ve 500 yanıtı döndürmek için yerleşik mekanizmalara sahiptir. Bir geliştirme ortamında, UseDeveloperExceptionPage middleware, hata ayıklama için paha biçilmez olan yığın izlemeleri dahil olmak üzere ayrıntılı hata bilgileri sağlar. Ancak, üretimde, bu ayrıntılı bilgiler (ve kesinlikle olmalıdır) potansiyel olarak hassas dahili uygulama ayrıntılarının sızmasını önlemek için bastırılır. Varsayılan üretim yanıtı genellikle basit, açıklayıcı olmayan bir 500 sayfası veya yanıtıdır.

Bu varsayılan davranış bilgi sızmasını önlerken, birkaç alanda yetersiz kalır:

  1. Bağlam Eksikliği: Genel bir 500 yanıtı, API tüketicisine (bir ön uç uygulaması veya başka bir hizmet olsun) neyin başarısız olduğuna dair belirli bir bilgi vermez, bu da sorunu anlamalarını veya etkili bir şekilde rapor etmelerini zorlaştırır.
  2. Tutarsız Hata Biçimi: Uygulamanızın farklı bölümleri, istemeden farklı görünen 500 hatalarına neden olabilir ve bu da tutarsız bir API deneyimine yol açar.
  3. Hata Ayıklama Zorlukları: 500 yanıtına bağlı uygun günlüğe kaydetme olmadan, bir üretim ortamında temel nedeni teşhis etmek önemli ölçüde zorlaşır.
  4. Kayıp İşlem Durumu: Genel bir 500, başarısız istek bağlamına özgü önemli temizleme veya günlüğe kaydetme işlemleri gerçekleştirme şansı vermeyebilir.

Bu nedenle, 500 hatalarının nasıl oluşturulduğu ve ele alındığı üzerinde kontrol sahibi olmak, profesyonel düzeyde API'ler oluşturmanın önemli bir yönüdür.

Denetleyicilerden Açıkça 500 Hata Döndürme

Bazen, denetleyici eyleminiz içinden, genellikle beklenmedik bir şekilde başarısız olabilecek bir işlem denedikten sonra bir catch bloğu içinde, açıkça bir iç sunucu hatası sinyali vermeniz gerekir. ASP.NET Core bunu başarmak için çeşitli yollar sunar.

StatusCode() Yardımcı Yöntemi:
ControllerBase'den miras alan denetleyicilerde bulunan en doğrudan yol, StatusCode() yöntemidir.

[HttpPost]
public IActionResult Post([FromBody] string something)
{
    try
    {
        // Başarısız olabilecek bir işlem deneyin
        _myService.ProcessSomething(something);
        return Ok();
    }
    catch (Exception ex)
    {
        // Özel durum ayrıntılarını günlüğe kaydedin (esastır!)
        _logger.LogError(ex, "İsteği işlerken beklenmedik bir hata oluştu.");

        // 500 durum kodu döndür
        return StatusCode(500);
    }
}

Daha iyi okunabilirlik için ve "sihirli sayılardan" kaçınmak için, Microsoft.AspNetCore.Http.StatusCodes içinde tanımlanan sabitleri kullanabilirsiniz:

return StatusCode(StatusCodes.Status500InternalServerError);

Yanıt Gövdesi ile StatusCode():
Genellikle, 500 durumuyla birlikte basit bir hata mesajı veya nesnesi döndürmek istersiniz. StatusCode() yönteminin bunun için bir aşırı yüklemesi vardır:

catch (Exception ex)
{
    _logger.LogError(ex, "Beklenmedik bir hata oluştu.");
    var errorResponse = new { message = "Bir iç sunucu hatası oluştu. Lütfen daha sonra tekrar deneyin." };
    return StatusCode(StatusCodes.Status500InternalServerError, errorResponse);
    // Veya sadece:
    // return StatusCode(500, "Bir iç sunucu hatası oluştu.");
}

Problem() Yardımcı Yöntemi ve ProblemDetails:
ASP.NET Core, HTTP API'lerinde hata ayrıntılarını döndürmek için ProblemDetails'in (RFC 7807'de tanımlanmıştır) kullanımını teşvik eder. Bu, hata yanıtları için standartlaştırılmış, makine tarafından okunabilir bir biçim sağlar. Denetleyiciler, bir ProblemDetails yükü içeren bir ObjectResult oluşturan bir Problem() yardımcı yöntemi sağlar. Varsayılan olarak, bir özel durum yakalandığında (ve HttpContext.Features.Get<IExceptionHandlerFeature>()) aracılığıyla kullanılabilir hale getirildiğinde, argümanlar olmadan Problem()'ı çağırmak genellikle 500 yanıtı oluşturur.

catch (Exception ex)
{
    _logger.LogError(ex, "Beklenmedik bir hata oluştu.");
    // Birçok özel durum senaryosunda varsayılan olarak Durum = 500 olan bir ProblemDetails yanıtı döndürür
    // Ayrıntıları otomatik olarak ayarlamak için etkili olması için özel durum işleme middleware'i gerektirebilir.
    // Ayrıca açık da olabilirsiniz:
    return Problem(detail: "İsteğinizi işlerken bir iç hata oluştu.", statusCode: StatusCodes.Status500InternalServerError);
}

ProblemDetails nesnesi, daha zengin, standartlaştırılmış bir hata açıklaması sunan type, title, status, detail ve instance gibi alanları içerir. Bu yaklaşımı kullanmak genellikle tutarlılık için önerilir.

ObjectResult'i Doğrudan Kullanma:
Özel durum filtreleri gibi standart denetleyici eylemleri dışındaki senaryolarda, sonucu daha manuel olarak oluşturmanız gerekebilir. Bir ObjectResult oluşturabilir ve durum kodunu ayarlayabilirsiniz.

// Genellikle bir IExceptionFilter içinde kullanılır
public void OnException(ExceptionContext context)
{
    _logger.LogError(context.Exception, "İşlenmemiş özel durum oluştu.");

    var details = new ProblemDetails
    {
        Status = StatusCodes.Status500InternalServerError,
        Title = "Beklenmedik bir hata oluştu.",
        Detail = "Bir iç sunucu hatası, isteğin tamamlanmasını engelledi.",
        Instance = context.HttpContext.Request.Path
    };

    context.Result = new ObjectResult(details)
    {
        StatusCode = StatusCodes.Status500InternalServerError
    };
    context.ExceptionHandled = true;
}

Genel Özel Durum İşleme Stratejileri

Denetleyicilerdeki try-catch blokları, belirli öngörülen hatalar için kullanışlı olsa da, tüm potansiyel hatalar için yalnızca onlara güvenmek, eylem yöntemlerini kirletir ve DRY (Don't Repeat Yourself - Kendini Tekrar Etme) ilkesini ihlal eder. Genel özel durum işleme mekanizmaları, beklenmedik hataları yönetmek için merkezi bir yol sağlar.

Özel Durum İşleme Middleware:
Pipelineda erken oturan özel middleware yazabilirsiniz. Bu middleware, sonraki middleware çağrılarını (MVC/yönlendirme ve denetleyici yürütmeniz dahil) bir try-catch bloğuna sarar. Bir özel durum yukarı doğru kabarcıklaşırsa, middleware onu yakalar, günlüğe kaydeder ve standartlaştırılmış bir 500 yanıtı oluşturur (genellikle ProblemDetails kullanarak).

// Basitleştirilmiş Örnek Middleware
public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ErrorHandlingMiddleware> _logger;

    public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "İşlenmemiş bir özel durum oluştu.");
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/problem+json";
        context.Response.StatusCode = StatusCodes.Status500InternalServerError;

        var details = new ProblemDetails
        {
            Status = StatusCodes.Status500InternalServerError,
            Title = "Beklenmedik bir hata oluştu.",
            Detail = "Bir iç sunucu hatası, isteğin başarıyla tamamlanmasını engelledi." // İstemci için genel mesaj
        };

        return context.Response.WriteAsJsonAsync(details);
    }
}

// Program.cs veya Startup.cs'de kaydedin
// app.UseMiddleware<ErrorHandlingMiddleware>();

UseExceptionHandler Middleware:
ASP.NET Core, bu amaç için özel olarak tasarlanmış yerleşik middleware sağlar: UseExceptionHandler. Bunu Program.cs'nizde (veya Startup.Configure'da) yapılandırıyorsunuz. Pipelineda daha sonra işlenmemiş bir özel durum oluştuğunda, bu middleware onu yakalar ve belirttiğiniz alternatif bir yolu kullanarak istek pipelineni yeniden yürütür. Bu yol genellikle özel bir hata işleme denetleyici eylemine işaret eder.

// Program.cs'de (.NET 6+)
if (app.Environment.IsDevelopment())
{
    app.UseDeveloperExceptionPage(); // Geliştirmede ayrıntılı hataları gösterir
}
else
{
    // Üretim hatası işleme
    app.UseExceptionHandler("/Error"); // /Error yoluna dahili olarak yönlendirir
    app.UseHsts();
}

// İlgili Hata Denetleyicisi
[ApiController]
[ApiExplorerSettings(IgnoreApi = true)] // Swagger'dan gizle
public class ErrorController : ControllerBase
{
    [Route("/Error")]
    public IActionResult HandleError()
    {
        var exceptionHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();
        var exception = exceptionHandlerFeature?.Error; // Orijinal özel durumu alın

        // Özel durumu günlüğe kaydet (exception değişkeni null olabilir)
         _logger.LogError(exception, "Genel işleyici tarafından yakalanan işlenmemiş özel durum.");


        // Bir ProblemDetails yanıtı döndür
        return Problem(detail: "Bir iç sunucu hatası oluştu.", statusCode: StatusCodes.Status500InternalServerError);
    }
     // Gerekirse ILogger enjeksiyonu için oluşturucu ekleyin
     private readonly ILogger<ErrorController> _logger;
     public ErrorController(ILogger<ErrorController> logger) { _logger = logger; }

}

Bu yaklaşım, hata işleme mantığını ana uygulama akışınızdan ayrı tutar.

Özel Durum Filtreleri (IExceptionFilter, IAsyncExceptionFilter):
Filtreler, MVC eylem yürütme hattına bağlanmanın bir yolunu sağlar. Özel durum filtreleri, bir eylem yönteminde veya eylem sonucu yürütme sırasında, model bağlama gerçekleştikten sonra ancak sonuç yanıt gövdesine yazılmadan önce işlenmemiş bir özel durum oluştuğunda özel olarak çalışır. MVC eylemlerine özgü hata işlemeye ihtiyacınız varsa, middleware'den daha ayrıntılı bir yaklaşım sunarlar. Daha önce gösterilen ObjectResult örneği genellikle bir özel durum filtresi içinde uygulanır.

Günlüğe Kaydetmenin Kritik Rolü

500 hatasını nasıl işlediğinizden ve istemciye ne döndürdüğünüzden bağımsız olarak, orijinal özel durumu günlüğe kaydetmek pazarlık konusu değildir. İstemci, muhtemelen rapor edebilecekleri benzersiz bir hata kimliği ile birlikte genel, güvenli bir hata mesajı (örneğin, "Bir iç sunucu hatası oluştu") almalıdır. Ancak, sunucu tarafı günlükleriniz tam ayrıntıları içermelidir:

Kapsamlı günlüğe kaydetme olmadan, üretimde aralıklı veya karmaşık 500 hatalarını teşhis etmek neredeyse imkansız hale gelir. Güvenilir bir hedefe (konsol, dosya, Seq, Splunk, Elasticsearch, Azure Application Insights gibi merkezi bir günlüğe kaydetme sistemi) yazmak üzere yapılandırılmış sağlam bir günlüğe kaydetme çerçevesi (Serilog, NLog veya yerleşik ILogger gibi) kullanın.

500 Hatalarını Hata Ayıklama

Özellikle üretimde bir 500 hatasıyla karşılaştığınızda:

  1. Günlükleri Kontrol Edin: Bu her zaman ilk adımdır. Hatanın meydana geldiği zamanın etrafında günlüğe kaydedilen tam özel durum ayrıntılarını arayın.
  2. Geliştirme Ortamı: UseDeveloperExceptionPage'in etkin olduğundan emin olun. Bu genellikle yanıt sayfasında tam özel durumu gösterir.
  3. Yerel Olarak Yeniden Oluşturun: İstek koşullarını (yük, başlıklar) yerel geliştirme ortamınızda bir hata ayıklayıcı eklenmiş olarak çoğaltmaya çalışın.
  4. Uygulama İzleme: Azure Application Insights gibi araçlar, işlenmemiş özel durumları otomatik olarak yakalar ve istek telemetrisi, bağımlılık çağrıları ve yığın izlemeleri dahil olmak üzere zengin bir bağlam sağlar.
  5. Yaygın Nedenler: Sık görülen suçlulara dikkat edin:

En İyi Uygulamalar Özeti

Sonuç

500 Internal Server Errors'ı etkili bir şekilde ele almak, iyi tasarlanmış bir ASP.NET Core Web API'nin bir özelliğidir. Varsayılan çerçeve davranışının ötesine geçerek ve StatusCode() veya Problem() gibi açık hata döndürme mekanizmalarını uygulayarak, sağlam genel özel durum işleme stratejileriyle (UseExceptionHandler veya özel middleware) ve kapsamlı günlüğe kaydetmeyle birleştirildiğinde, geliştiriciler yalnızca işlevsel değil, aynı zamanda dayanıklı, hata ayıklaması daha kolay olan ve sunucuda beklenmedik bir şekilde bir şeyler ters gittiğinde bile tüketiciler için daha iyi bir deneyim sağlayan API'ler oluşturabilirler.

💡
Harika bir API Dokümantasyonu oluşturan harika bir API Test aracı mı istiyorsunuz? Güzel API Dokümantasyonu?

Geliştirici Ekibinizin maksimum verimlilikle birlikte çalışması için entegre, Hepsi Bir Arada bir platform mu istiyorsunuz?

Apidog tüm taleplerinizi karşılıyor ve Postman'in yerini çok daha uygun bir fiyata alıyor!
button

API Tasarım-Öncelikli Yaklaşımı Apidog'da Uygulayın

API'leri oluşturmanın ve kullanmanın daha kolay yolunu keşfedin