Asp.net-Web-Api

Elmah 不使用帶有 HttpResponseException 的 WebAPI 記錄異常

  • March 7, 2016

在我的 WebApi 程式碼中,我引發了一個 HttpResponseException ,它使請求管道短路並生成一個有效的 Http 響應。但是,我正在嘗試將 webApi 與 elmah 日誌記錄集成,但 HttpResponseExeptions 沒有出現。

我為 elmah 設置了 web.config 並具有以下程式碼:

在 Global.asx.cs 中:

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

篩選:

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

引發異常的程式碼:

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"));
   }            
}   

在此之前實施過此操作的任何人都可以讓我知道我做錯了什麼嗎?

Web API 特殊情況 HttpResponseException 在操作中引發並轉換為 HttpResponseMessage,因此您沒有看到您的異常過濾器被呼叫。

在從過濾器中拋出 HttpResponseException 的情況下,情況並非如此。但是,理想情況下,不需要從過濾器中拋出 HttpResponseException,因為您可以通過在提供的輸入上下文上設置 Response 屬性來短路請求。

如上所述,當您引發 HttpResponseException 時,Elmah 過濾器不會擷取和記錄任何內容。更具體地說,如果使用以下語法:

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"));

我想在這兩種情況下擷取並記錄錯誤。方法是使用“ActionFilterAttribute”,覆蓋“OnActionExecuted”,並檢查 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()));
       }
   }
}

另一方面,我還重寫了“OnActionExecuting”來驗證模型狀態。這使我可以刪除我的操作中的所有檢查。

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);
   }
}

當然,您需要使用“config.Filters.Add”添加過濾器。

引用自:https://stackoverflow.com/questions/16904041