ASP.NET Web Api'deki tüm işlenmemiş özel durumları yakala


113

ASP.NET Web Api'de oluşan tüm işlenmemiş özel durumları günlüğe kaydedebilmek için nasıl yakalayabilirim ?

Şimdiye kadar denedim:

  • Oluşturun ve kaydedin ExceptionHandlingAttribute
  • Bir Application_Erroryöntem uygulayınGlobal.asax.cs
  • Abone olmak AppDomain.CurrentDomain.UnhandledException
  • Abone olmak TaskScheduler.UnobservedTaskException

ExceptionHandlingAttributeBaşarıyla örneğin, kontrolör eylem yöntemleri ve eylem filtreleri içinde atılan, ancak diğer istisnalar işlenmez durumları işleme:

  • IQueryableBir eylem yöntemi tarafından döndürülen bir çalıştırma başarısız olduğunda istisnalar atılır
  • Bir ileti işleyicisi tarafından atılan istisnalar (ör. HttpConfiguration.MessageHandlers)
  • Bir denetleyici örneği oluşturulurken atılan istisnalar

Temel olarak, bir istisna istemciye 500 Dahili Sunucu Hatasının döndürülmesine neden olacaksa, günlüğe kaydedilmesini istiyorum. Uygulama Application_Errorbu işi Web Formlarında ve MVC'de iyi yaptı - Web Api'de ne kullanabilirim?


ASP.NET Health Monitoring kullanmayı denediniz mi? Sadece etkinleştirin ve istisnalarınızın olay günlüğüne kaydedilip kaydedilmediğini görün.
John Saunders

Sistem Durumu İzleme MVC ardışık düzen istisnalarımı yakalar, ancak Web Api ardışık düzen istisnalarımı yakalamaz.
Joe Daley

Teşekkürler - Yapıcı / bağımlılık ekleme sorunlarımı neden günlüğe
kaydedemediğimi anlamam

Yanıtlar:


156

Bu artık WebAPI 2.1 ile mümkündür ( Yeniliklere bakın ):

IExceptionLogger'ın bir veya daha fazla uygulamasını oluşturun. Örneğin:

public class TraceExceptionLogger : ExceptionLogger
{
    public override void Log(ExceptionLoggerContext context)
    {
        Trace.TraceError(context.ExceptionContext.Exception.ToString());
    }
}

Ardından, uygulamanızın HttpConfiguration ile, aşağıdaki gibi bir yapılandırma geri aramasının içinde kaydolun:

config.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

veya doğrudan:

GlobalConfiguration.Configuration.Services.Add(typeof(IExceptionLogger), new TraceExceptionLogger());

7
@NeilBarnwell Evet, System.Web.Http montaj sürümüne Web API 2.1 karşılık 5.1.0 . Yani burada açıklanan çözümü kullanmak için bu sürüme veya üstüne ihtiyacınız var. Bkz Nuget paket sürümlerini
decates

2
Bazı 500 hata hala buna yakalanmıyor, örn. HttpException - uzak ana bilgisayar bağlantıyı kapattı. Global.asax Application_Error'ın web api işleme dışındaki hataları işleyebileceği bir yer var mı?
Avner

11
Resmi doco'nun msdn'de ne kadar ayrıntılı olduğunu ve geliştiricilerin% 99'unun gerçekten istediği şey, hataları günlüğe kaydetmek için yalnızca 8 satırlık koddur.
Rocklan

20

Yuval'ın cevabı, bağlantılı sayfada belirtildiği gibi günlük kaydı için değil, Web API tarafından yakalanan işlenmemiş istisnalara yönelik yanıtları özelleştirmek içindir . Ayrıntılar için sayfadaki Ne Zaman Kullanılmalı bölümüne bakın. Kaydedici her zaman çağrılır, ancak işleyici yalnızca bir yanıt gönderilebildiğinde çağrılır. Kısaca, günlüğe kaydetmek için kaydediciyi ve yanıtı özelleştirmek için işleyiciyi kullanın.

Bu arada, derleme v5.2.3 kullanıyorum ve ExceptionHandlersınıfın HandleCoreyöntemi yok. Bence eşdeğeri Handle. Ancak, basitçe alt sınıflandırma ExceptionHandler(Yuval'ın cevabında olduğu gibi) işe yaramaz. Benim durumumda IExceptionHandleraşağıdaki gibi uygulamalıyım .

internal class OopsExceptionHandler : IExceptionHandler
{
    private readonly IExceptionHandler _innerHandler;

    public OopsExceptionHandler (IExceptionHandler innerHandler)
    {
        if (innerHandler == null)
            throw new ArgumentNullException(nameof(innerHandler));

        _innerHandler = innerHandler;
    }

    public IExceptionHandler InnerHandler
    {
        get { return _innerHandler; }
    }

    public Task HandleAsync(ExceptionHandlerContext context, CancellationToken cancellationToken)
    {
        Handle(context);

        return Task.FromResult<object>(null);
    }

    public void Handle(ExceptionHandlerContext context)
    {
        // Create your own custom result here...
        // In dev, you might want to null out the result
        // to display the YSOD.
        // context.Result = null;
        context.Result = new InternalServerErrorResult(context.Request);
    }
}

Kaydediciden farklı olarak, işleyicinizi ekleme yerine varsayılan işleyiciyi değiştirerek kaydettirdiğinizi unutmayın.

config.Services.Replace(typeof(IExceptionHandler),
    new OopsExceptionHandler(config.Services.GetExceptionHandler()));

1
Bu harika bir çözüm, bu, 'tüm hataları yakalamak veya günlüğe kaydetmek' için kabul edilen çözüm olmalıdır. ExceptionHandler'ı genişletirken neden benim için işe yaramadığını asla anlayamazdım.
Rajiv

Harika çözüm. MVC işlem hattı bir istek için yüklendikten sonra bu harika çalışıyor. IIS, OWIN'in startup.cs içinde döndürülmesi de dahil olmak üzere o zamana kadar istisnaları hala ele alıyor. Bununla birlikte, spin up bir noktada startup.cs'yi işlemeyi bitirir, işini harika bir şekilde yapar.
Gustyn

18

Kendi sorumu cevaplamak için bu mümkün değil!

Dahili sunucu hatalarına neden olan tüm istisnaları ele almak, Web API'sinin sahip olması gereken temel bir yetenek gibi görünüyor, bu nedenle Microsoft'tan Web API'si için Global hata işleyicisi için bir istek gönderdim :

https://aspnetwebstack.codeplex.com/workitem/1001

Kabul ediyorsanız, bu bağlantıya gidin ve ona oy verin!

Bu arada, mükemmel ASP.NET Web API Özel Durum İşleme makalesi, birkaç farklı hata kategorisini yakalamanın birkaç farklı yolunu gösterir. Olması gerekenden daha karmaşıktır ve tüm ara sunucu hatalarını yakalamaz , ancak bugün mevcut olan en iyi yaklaşımdır.

Güncelleme: Genel hata işleme artık uygulandı ve gecelik yapılarda mevcut! ASP.NET MVC v5.1 sürümünde yayınlanacaktır. Nasıl çalışacağı aşağıda açıklanmıştır: https://aspnetwebstack.codeplex.com/wikipage?title=Global%20Error%20Handling


web api yerine ajax çağrıları için denetleyiciyi kullanmak için bir neden gibi görünüyor .. sınırlar zaten bulanık .. ELMAH onu yakalayabiliyorsa, belki bir yolu vardır
Sonic Soul

4
Küresel hata işleme artık Web API 2.1'e eklenmiştir. Daha fazla ayrıntı için cevabıma bakın.
decates

10

IExceptionHandlerArabirimi uygulayarak (veya ExceptionHandlertemel sınıfı devralarak ) genel bir istisna işleyicisi de oluşturabilirsiniz . Tüm kaydedildikten sonra yürütme zincirinde en son çağrılacak IExceptionLogger:

IExceptionHandler, tüm denetleyicilerden tüm işlenmemiş istisnaları işler. Bu listenin sonuncusu. Bir özel durum oluşursa, önce IExceptionLogger, ardından ExceptionFilters denetleyicisi ve hala işlenmemişse IExceptionHandler uygulaması çağrılır.

public class OopsExceptionHandler : ExceptionHandler
{
    public override void HandleCore(ExceptionHandlerContext context)
    {
        context.Result = new TextPlainErrorResult
        {
            Request = context.ExceptionContext.Request,
            Content = "Oops! Sorry! Something went wrong."        
        };
    }

    private class TextPlainErrorResult : IHttpActionResult
    {
        public HttpRequestMessage Request { get; set; }

        public string Content { get; set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            HttpResponseMessage response = 
                             new HttpResponseMessage(HttpStatusCode.InternalServerError);
            response.Content = new StringContent(Content);
            response.RequestMessage = Request;
            return Task.FromResult(response);
        }
    }
}

Daha fazlası burada .


Merak ediyorum, bu kayıt nerede?
ThunD3eR

-1

Farkında olmadığınız mevcut deneme bloklarına sahip olabilirsiniz.

Yeni global.asax.Application_Erroryöntemimin eski kodumuzda sürekli olarak işlenmemiş istisnalar için çağrılmadığını düşündüm .

Sonra çağrı yığınının ortasında, Exception metnine Response.Write adında birkaç try-catch bloğu buldum. İşte buydu. Metni ekrana attı, sonra istisna taşını öldürdü.

Böylece istisnalar ele alındı, ancak idare yararlı hiçbir şey yapmıyordu. Bu try-catch bloklarını kaldırdıktan sonra, beklendiği gibi Application_Error yöntemine yayılan istisnalar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.