2013-06-03 12 views
12

私のWebApiコードでは、リクエストパイプラインを短絡し、有効なHttp応答を生成するHttpResponseExceptionを発生させます。しかし、私はelmaのログとwebApiを統合しようとしていますが、HttpResponseExeptionsは表示されません。ElmahはHttpResponseExceptionでWebAPIを使用して例外を記録しません

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

私が間違っていることを知らせる前にこれを実装している人はいますか?

答えて

4

Web APIの特別なケースHttpResponseExceptionがアクションでスローされ、HttpResponseMessageに変換されるため、例外フィルタが呼び出されていません。

これは、フィルタからHttpResponseExceptionをスローする場合は当てはまりません。しかし、理想的には、フィルタからHttpResponseExceptionをスローする必要はありません。これは、指定された入力コンテキストでResponseプロパティを設定することによって要求を短絡させる可能性があります。

+2

どのように動作させるには? – jaffa

+0

できません。アクションからスローされると、非HttpResponseExceptionsに対してのみフィルタが呼び出されます。 –

+1

私はHttpResponseExceptionを作成するときに手動のElmahエラーシグナリングを使用しましたが、これは正常に動作するようです。 – jaffa

3

WebApiの期待どおりに動作させるには、HttpFiltersのElmahをオンにする必要があります。

NuGet Packageとして利用可能なElmah.Contrib.WebApiを使用すると、Elmah.Contrib.WebApiプロジェクトサイトの指示に従って配線することができるクラスが含まれます。

あなたがこれを自分でやりたいのであれば、Capturing Unhandled Exceptions in ASP.NET Web API's with ELMAHはElmah.Contrib.WebApiが何をしているかを案内します。私もElmah.MVC NuGet Packageの使用をお勧めします

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

はまた、私はそれがELMAHで取りに行くためにエラー応答がスローされる方法を変更しなければなりませんでした。

+5

あなたが参照しているプロジェクトもブログ投稿も@jaffaによって提起された質問に対処できません。属性またはグローバルフィルタを使用してASP.NET Web APIプロジェクトの例外をトラップすることは、Web上で十分に文書化されています。 Web APIが、 'HttpResponseExeption'が' ApiController'からスローされたときに、例外を除くすべての例外*に対して派生した例外フィルタでExceptionFilterAttribute.OnException()を呼び出すという事実です。この場合、Web APIは例外を取り込み、例外フィルタは呼び出されません。私は回避策を探していますが、まだ見つけていません。 –

+0

@KevinBabcockのリンクされた解決策は私のために働いた+1 – NimChimpsky

+0

これはHttpResponseExceptionを処理しません – lnaie

11

上記のように、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をチェックすることです。

さらに、モデル状態を検証するために「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」を使用してフィルタを追加する必要があります。

+0

私はそれがこの質問への良い答えだと思う... – Dragouf

+0

はい、これもHttpResponseExceptionをキャッチすることができます。 – lnaie

+0

多くのお役に立った!ありがとうございました。 – mike123

関連する問題