2013-06-03 8 views
12

W moim kodzie WebApi podniosłem wyjątek HttpResponseException, który powoduje zwarcie w potoku żądania i generuje poprawną odpowiedź Http. Jednak próbuję zintegrować webApi z logowaniem elmah, ale HttpResponseExeptions nie są wyświetlane.Elmah nie rejestruje wyjątków przy użyciu interfejsu WebAPI z HttpResponseException

mam web.config set-up na ELMAH i mają następujący kod:

W Global.asx.cs:

static void ConfigureWebApi(HttpConfiguration config) 
{ 
    config.Filters.Add(new ServiceLayerExceptionFilter());    
    config.Filters.Add(new ElmahHandledErrorLoggerFilter()); 
    config.DependencyResolver = new WebApiDependencyResolver(ObjectFactory.Container);        
}  

Filtr:

public class ElmahHandledErrorLoggerFilter : ExceptionFilterAttribute 
{ 
    public override void OnException(HttpActionExecutedContext actionExecutedContext) 
    { 
     base.OnException(actionExecutedContext); 
     ErrorSignal.FromCurrentContext().Raise(actionExecutedContext.Exception); 
    } 
} 

Kod, w którym zgłaszany jest wyjątek:

public Task<FileUpModel> UploadFile() 
{ 
    if (Request.Content.IsMimeMultipartContent()) 
    {     
     var provider = new TolMobileFormDataStreamProvider("C:\images\"); 

     var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(
     t => 
     { 

      if (t.IsFaulted || t.IsCanceled) 
       throw new HttpResponseException(HttpStatusCode.InternalServerError); 

      var fileInfo = provider.FileData.FirstOrDefault(); 
      if (fileInfo == null) 
       // the exception here isn't logged by Elmah?! 
       throw new HttpResponseException(HttpStatusCode.InternalServerError);  

      var uploadModel = new FileUpModel { success = true }; 
      return uploadModel; 
     }); 

     return task; 
    } 
    else 
    { 
     throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted")); 
    }    
} 

Czy ktoś, kto wdrożył to wcześniej, dał mi znać, co robię źle?

Odpowiedz

4

Przypadki specjalne Web API Wyjątek HttpResponseException jest zgłaszany w akcji i konwertowany na HttpResponseMessage, przez co nie jest wyświetlany wywoływany filtr wyjątków.

Nie jest to prawdą w przypadku wyrzucenia wyjątków HttpResponseException z filtrów. Jednak najlepiej nie trzeba wyrzucać wyjątków HttpResponseException z filtrów, ponieważ można spowodować zwarcie żądania, ustawiając właściwość Response w dostarczonym kontekście wejściowym.

+2

Jak mogę go uruchomić? – jaffa

+0

Nie możesz. Twój filtr zostanie wywołany tylko dla wyjątków HttpResponseException, gdy zostanie wyrzucony z działania. –

+1

Podczas tworzenia wyjątku HttpResponseException użyłem ręcznego sygnalizowania błędu Elmah i wygląda na to, że działa dobrze. – jaffa

3

Musisz włączyć Elmah dla HttpFilters, aby to działało zgodnie z oczekiwaniami dla WebApi.

Dostępne jako Elmah.Contrib.WebApi dostępne jako , będzie zawierał klasę, którą można następnie podłączyć zgodnie z instrukcjami na stronie projektu Elmah.Contrib.WebApi.

Jeśli chcesz zrobić to sam, Capturing Unhandled Exceptions in ASP.NET Web API's with ELMAH przeprowadzi Cię przez to, co robi dla Ciebie Elmah.Contrib.WebApi.

Dodatkowo musiałem zmienić sposób, że odpowiedź zostanie zgłoszony błąd na to, aby być odebrane przez ELMAH do:

throw new HttpException((int)HttpStatusCode.NotAcceptable, "This request is not properly formatted"); 

Chciałbym również polecić korzystanie z Elmah.MVC NuGet Package.

+5

Ani projekt, ani blog, do którego się odwołujesz, nie odpowiadają na pytanie zadane przez @jaffa. Użycie atrybutu lub filtru globalnego do pułapkowania wyjątków w projekcie ASP.NET Web API jest dobrze udokumentowane w Internecie. Co * nie jest * dobrze udokumentowane, to fakt, że Web API wywołuje ExceptionFilterAttribute.OnException() na pochodzącym filtrze wyjątków dla każdego wyjątku * z wyjątkiem *, gdy 'HttpResponseExeption' jest generowany z' ApiController'. W takim przypadku interfejs Web API połknie wyjątek, a filtr wyjątków nigdy nie zostanie wywołany. Szukałem obejścia, ale jeszcze go nie znaleziono. –

+0

@KevinBabcock połączone rozwiązanie działało dla mnie +1 – NimChimpsky

+0

To nie obsługuje HttpResponseException – lnaie

11

Jak wspomniano powyżej, filtr Elmah nie przechwytuje i nie rejestruje niczego podczas podnoszenia wyjątku HttpResponseException. Dokładniej, jeśli stosuje się następującą składnię:

return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "It was a bad request"); 
or 
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "HttpResponseException - This request is not properly formatted")); 

Chciałem pułapkę i logowania błąd w obu przypadkach. Aby to zrobić, użyj "ActionFilterAttribute", zastąp "OnActionExecuted" i sprawdź actionExecutedContext.Response.IsSuccessStatusCode.

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
{ 
    // when actionExecutedContext.Response is null, the error will be caught and logged by the Elmah filter 
    if ((actionExecutedContext.Response != null) && !actionExecutedContext.Response.IsSuccessStatusCode) 
    { 
     try 
     { 
      var messages = (System.Web.Http.HttpError)((System.Net.Http.ObjectContent<System.Web.Http.HttpError>)actionExecutedContext.Response.Content).Value; 
      StringBuilder stringBuilder = new StringBuilder(); 
      foreach (var keyValuePair in messages) { 
       stringBuilder.AppendLine("Message: Key - " + keyValuePair.Key + ", Value - " + keyValuePair.Value); 
      } 
      Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Web API Failed Status Code returned - " + stringBuilder.ToString())); 
     } 
     catch (Exception ex) 
     { 
      Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Error in OnActionExecuted - " + ex.ToString())); 
     } 
    } 
} 

Na marginesie, również nadpisuję "OnActionExecuting", aby sprawdzić stan modelu. Pozwoliło mi to na usunięcie wszystkich czeków w ramach moich działań.

public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext) 
{ 
    if (actionContext.ModelState != null && !actionContext.ModelState.IsValid) 
    { 
     StringBuilder stringBuilder = new StringBuilder(); 
     foreach (var obj in actionContext.ModelState.Values) 
     { 
      foreach (var error in obj.Errors) 
      { 
       if(!string.IsNullOrEmpty(error.ErrorMessage)) { 
        stringBuilder.AppendLine("Error: " + error.ErrorMessage); 
       } 
      } 
     } 
     Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Invalid Model State -- " + stringBuilder.ToString())); 
     actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState); 
    } 
} 

Oczywiście należy dodać filtr za pomocą "config.Filters.Add".

+0

Myślę, że to dobra odpowiedź na to pytanie ... – Dragouf

+0

Tak, jest to również w stanie złapać wyjątek HttpResponseException. – lnaie

+0

Pomógł dużo! Dziękuję Ci. – mike123

Powiązane problemy