ASP.NET MVC'de Genel Hata Yönetimi

Yazdığımız projelerde kod hatalarının bulunabilme ihtimali her zaman vardır. Bu hatalar tamamen bizden kaynaklı olabilir veya tahmin edemediğimiz durumlarda ortaya çıkabilir. Bu gibi durumlarda hatanın kaynağının direkt olarak son kullanıcıya gösterilmesi hem görsellik açısından güzel bir durum değildir, hem de projemizdeki bazı kodların son kullanıcıya gösterilmesine yani güvenlik zaafiyetine yol açabilir. Mesela kullanıcı sitemizde var olmayan bir adrese gitmek isteyebilir. Bu nedenle projede meydana gelebilecek herhangi bir hatayı merkezi olarak yönetebilmemiz gerekmektedir. ASP.NET bu amaçla etkili bir hata yönetimi (error handling) sunmaktadır. Uygulamamızda tüm request ve response'lerin yönetildiği, bunlara ait event'ların yakalandığı Global.asax dosyasında uygulamanın herhangi bir bölümünde herhangi bir kaynaktan dolayı meydana gelen hataların yakalanacağı Application_Error() metodunu kullanabiliriz. Bu metodu kullanarak herhangi bir hata meydana geldiğinde ASP.NET'in tipik hata sayfalarını göstermek yerine özel hata sayfalarımızı kullanıcılara gösterebiliriz. Bu sayede uygulamada oluşan hataları veritabanına yazdırabilir veya kendimize mail olarak gönderebiliriz.

protected void Application_Error()
{
    var exception = Server.GetLastError(); //Oluşan hatayı değişkene atadık.
    //Eğer hata kaydı (log) tutulacak ise gerekli kodlar buraya.
    var httpException = exception as HttpException;
    Response.Clear();
    Server.ClearError(); //Sunucudaki hatayı temizledik.
    Response.TrySkipIisCustomErrors = true//IIS'in tipik hata sayfalarını görmezden geldik.
    var routeData = new RouteData();
    routeData.Values["controller"] = "Error"//Hata mesajlarını yöneteceğimiz Controller ismi
    routeData.Values["action"] = "Index"//Controller içindeki default Action ismi
    routeData.Values["exception"] = exception;
    Response.StatusCode = 500;

    if (httpException != null)
    {
        Response.StatusCode = httpException.GetHttpCode();

        switch (Response.StatusCode)
        {
            case 403: //Eğer 403 hatası meydana gelmiş ise Http403 Action'ı devreye girecek.
                routeData.Values["action"] = "Http403";
                break;

            case 404: //Eğer 404 hatası meydana gelmiş ise Http404 Action'ı devreye girecek.
                routeData.Values["action"] = "Http404";
                break;
        }
    }

    IController errorsController = new Controllers.ErrorController();
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
    errorsController.Execute(rc);
}

Şimdi yakalanan hataları kullanıcılara gösterebilmemiz için Model, Controller ve View'ı oluşturalım.

ErrorModel

public class ErrorModel
{
    public string ErrorTitle { getset; }
    public Exception ExceptionDetail { getset; }
}

ErrorController

public ViewResult Index(Exception exception)
{
    return View("Error"new ErrorModel { ErrorTitle = "Bir Hata Meydana Geldi", ExceptionDetail = exception });
}

public ViewResult Http404()
{
    return View("Error"new ErrorModel { ErrorTitle = "Sayfa Bulunamadı" });
}

public ViewResult Http403()
{
    return View("Error"new ErrorModel { ErrorTitle = "Yasaklı içerik" });
}

Ve son olarak View dosyamız

@model MvcApplication1.Models.ErrorModel
@{
    Layout = "~/Views/Shared/_Layout.cshtml";
    ViewBag.Title = Model.ErrorTitle;
}

@if (Response.StatusCode == 404)
{
    <img src="/content/images/error/404.png" alt="Sayfa Bulunamadı" />
}
else
{
    if (Model.ExceptionDetail != null)
    {
        @Model.ExceptionDetail.Message
    }
}
Mehmet YAYLACI
YORUMLAR (11)
  1. Yavuz Ağca
    Yavuz Ağca - Cevapla

    23 Ekim 2013 - 11:38

    Merhaba, Elinize sağlık güzel bir makale olmuş fakat sormak istediğim bir kaç sorum var şimdiden teşekkürler; 1- projeme kodları ekledim (Global .asax.cs içine Application Error metodunu) fakat olmayan bir url isteği yaptığımda case 404 giriyor sonra errorsController.Execute(rc); satırında "Only one 'model' statement is allowed in a file." hatasını veriyor errorController içeriside sizin makalede yaptığınız gibi 2 - benim şu şekilde bir url yapım var /view/sayfa url/dil (ürün/beyaz-dikenler/TR/) bu urlde dili veya sayfa url sildiğimde httpException nesnesi null gelmiyor ama view isminde bir değişiklik yaptığımda httpException null dönüyor sizce neden kaynaklana bilir.

    • Mehmet YAYLACI
      Mehmet YAYLACI - Cevapla

      28 Aralık 2013 - 19:28

      Merhaba. Öncelikle mail sunucusunda problem yaşamam nedeniyle mesajınızı yeni gördüm. Kusura bakmayın. Hatanıza gelince bir View'da sadece 1 model kullanabileceğiniz için hatayı alıyorsunuz. Tabi proje dosyalarını görmeden maalesef tam bir cevap veremeyeceğim. Kolay gelsin.

  2. Remzi Altın
    Remzi Altın - Cevapla

    15 Mayıs 2014 - 17:11

    Hocam bende bu hatayı verdi neden olabilir? Sorry, an error occurred while processing your request.

    • Mehmet YAYLACI
      Mehmet YAYLACI - Cevapla

      15 Mayıs 2014 - 17:38

      Web.config dosyanızda

      <system.web>

      düğümü altında

      <compilation debug="true" />
      <customErrors mode="Off" />
      ayarlarını uygularsanız sorununuzun ne olduğunu daha kolay anlayabilirsiniz.

  3. Oğuzhan SARI
    Oğuzhan SARI - Cevapla

    29 Ocak 2016 - 21:48

    Merhaba, Bilgiler için teşekkürler. Bende şöyle bir sıkıntı mevcut. localhost:888/Index/olmayansayfa yazdığımda hata sayfası sorunsuz geliyor. Fakat localhost:888/olmayansayfa şeklinde yazdığımda hata sayfası kaynak kodu text metin olarak gözüküyor. Daha doğrusu controller altında action yoksa hata sayfası normal gözüküyor. Fakat controller veya controller ile action olmayan bir linkte hata sayfası text metin olarak gözüküyor. Çözümü ne olabilir?

    • Mehmet YAYLACI
      Mehmet YAYLACI - Cevapla

      29 Ocak 2016 - 23:20

      Merhaba. Acaba Application_Error() metodunu Global.asax dosyası yerine Controller içinde tanımlıyor olabilir misiniz?

      • Oğuzhan SARI
        Oğuzhan SARI - Cevapla

        30 Ocak 2016 - 17:57

        Yok hayır. Global.asax ta yazılı. Yazdığım kodların ekran görüntüleri.
        Global.asax http://oguzhansari.com/files/mvcerrorpage/1.png
        Models içinde ErrorModel.cs http://oguzhansari.com/files/mvcerrorpage/2.png
        ErrorModel.cs İçeriği http://oguzhansari.com/files/mvcerrorpage/3.png
        ErrorController.cs içeriği http://oguzhansari.com/files/mvcerrorpage/4.png
        Error > Index.cshtml içeriği http://oguzhansari.com/files/mvcerrorpage/5.png

        • Mehmet YAYLACI
          Mehmet YAYLACI - Cevapla

          30 Ocak 2016 - 21:55

          Kodlarda hata göremedim. Başka bir sebepten olmalı. Umarım çözebilirsiniz.

  4. Ayşen Sonkunduracı
    Ayşen Sonkunduracı - Cevapla

    05 Mayıs 2017 - 01:46

    Hakikaten çok güzel anlatmışınız. Ne zamandır aradığım bir konu idi çok makbule geçti teşekkürler. :)

  5. Ahmet TÜRKÖZ
    Ahmet TÜRKÖZ - Cevapla

    21 Ekim 2017 - 12:00

    Hocam öncelikle paylaşımınız için teşşekürler. Bende Oğuzhan SARI arkadaşımızın söylemeye çalıştığı sorun ile karşılaştım. Eğer ana dizinden sonra olmayan bir controller şeklinde bir ifade yazarsak örn: localhost/olmayanbircontroller browserda sayfanın kaynak kodunu açıyor.Routeconfig dosyasında bir kontrol gerekiyor sanki ama bende başaramadım. Debug edildiğinde tespit şu şekilde= routeData.Values=exceptions={"The controller for path '/Homekjhk' was not found or does not implement IController."} olduğunda gerçekliyor.

  6. Muhammet
    Muhammet - Cevapla

    23 Mayıs 2018 - 11:37

    Bende Ahmet Türköz ve Oğuzhan Sarı arkadaşımızın yaşadığı sorunu yaşıyorum çözüm bulan varmı ?

YORUM FORMU