2017-09-06 5 views
0

Ich entwickle eine ASP.NET-Web-API, in einer meiner Controller-Aktionen verwende ich einen Task.Factory.StartNew-Aufruf.ExceptionFilterAttribute wird nicht ausgelöst, wenn Task.Factory.StartNew verwendet wird

Dies löst jedoch nicht den Ausnahmefilter aus, den ich konfiguriere, wenn eine Ausnahme in der Aufgabe ausgelöst wird.

Controller.cs

public class MyController : ApiController 
{ 
    [HttpPost] 
    public HttpResponseMessage Post() 
    { 
     Task.Factory 
      .StartNew(() => DoTheThing()) 
      .ContinueWith(tsk => { throw new Exception("Webhook Exception", tsk.Exception); }, TaskContinuationOptions.OnlyOnFaulted); 

     return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
} 

ExceptionFilter.cs

public class ExceptionFilter : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext context) 
    { 
     throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.InternalServerError) 
     { 
      Content = new ObjectContent(typeof(object), new 
      { 
       Message = "Critical Error", 
       ExceptionMessage = "An error occurred, please try again or contact the administrator.", 
       Type = ExceptionType.Unhandled 
      }, new JsonMediaTypeFormatter()), 
      ReasonPhrase = "Critical Error" 
     }); 
    } 
} 

Global.asax.cs

public class MyApplication : HttpApplication 
{ 
    protected void Application_Start() 
    {    
     GlobalConfiguration.Configuration.Filters.Add(new ExceptionFilter()); 
    } 
} 

I kann debuggen und die ContinueWith-Methode wird ausgelöst und die neue Ausnahme wird ausgelöst. Aber der Filter wird nicht ausgelöst.

+0

Sie beobachten nicht die (re) geworfene 'Exception', daher handelt es sich um eine' Unbeachtete Ausnahme'. Siehe: [Behandlung von Ausnahmebedingungen in .NET 4.5] (https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/) – IronGeek

+0

Danke für der Link, ich glaube ich verstehe das Problem jetzt. Ich versuche das Unmögliche möglich zu machen, da der Filter nur Ausnahmen in meiner Aktion abfängt. Aber ich möchte, dass meine Aktion unmittelbar vor dem Ende meiner Aufgabe zurückkehrt. – Joe

Antwort

2

Der Filter wird nicht ausgelöst, da die Ausnahme im Thread anders als im Thread der Controller-Aktionsmethode ausgelöst wird. Sie könnten:

  1. Await Aufgabe

    [HttpPost] 
    public async Task<HttpResponseMessage> Post() 
    { 
        await Task.Factory 
         .StartNew(() => DoTheThing()) 
         .ContinueWith(tsk => { throw new Exception("Webhook Exception", tsk.Exception); }, TaskContinuationOptions.OnlyOnFaulted); 
    
        return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
    
  2. Warten Aufgabe

    [HttpPost] 
    public HttpResponseMessage Post() 
    { 
        var task = Task.Factory 
            .StartNew(() => DoTheThing()) 
            .ContinueWith(tsk => { throw new Exception("Webhook Exception", tsk.Exception); }, TaskContinuationOptions.OnlyOnFaulted); 
    
        task.Wait(); 
    
        return new HttpResponseMessage(HttpStatusCode.OK); 
    } 
    

Alle diese Ansätze rethrow die Ausnahme in Aktion-Methode und der Filter fängt ihn.

+0

Kennzeichnung als richtig, wie es meine Frage beantwortet. Es ist nicht die Lösung, die ich wollte, da ich sofort von meiner Aktion zurückkehren und nicht auf die Aufgabe warten wollte. Aber ich verstehe jetzt, dass dies im Konflikt mit dem Design des Filters steht, das nur Ausnahmen innerhalb eines Controller-Aktions-Threads abfängt. – Joe

+0

Tatsächlich fängt der Ausnahmefilter alle Ausnahmen ab, aber die Task "handhabt" sie im eigenen Thread. Wie auch immer, Sie geben den 'HttpStatusCode.OK' sofort von der Aktionsmethode zurück, aber dann geben Sie einen anderen Status - 'InternalServerError' vom Filter zurück. Die Anfrage wurde jedoch bereits bearbeitet und der Client hat eine Antwort erhalten. Sie könnten die Ausnahme in der Fortsetzungsaufgabe nach der Rückkehr von der Aktion protokollieren, aber nicht den Antwortstatus neu schreiben. –

Verwandte Themen