2012-07-10 3 views
19

にログを追加するためにどのように私はこれによるとApiControllerGet()ため[LoggedApiCall]フィルタを作成しようとしています:ASP.NET Web API ActionFilter exampleはMVC4 WEBAPI

私はSystem.Web.HttpFilters.ActionFilterAttributeを作成しました。 オーバーライドはOnActionExecuted(HttpActionExecutedContext actionExecutedContext)

私はおそらく、私はすべてのAPIが間違った道を呼び出すログインについてつもりHttpActionExecutedContext

から、発信者のIPを取得する方法を見つけることができないようすることができますか?

答えて

13

HttpConfiguration.Filtersに追加した次のフィルタを使用します。いくつかのコード:私たちはlog4netのを使用

internal class LoggingFilter : IExceptionFilter, IActionFilter 
{ 
    private readonly ILog log; 

    public LoggingFilter(ILog log) 
    { 
     if (log == null) 
     { 
      throw new ArgumentNullException("log"); 
     } 

     this.log = log; 
    } 

    public bool AllowMultiple 
    { 
     get { return false; } 
    } 

    Task IExceptionFilter.ExecuteExceptionFilterAsync(HttpActionExecutedContext actionContext, CancellationToken cancellationToken) 
    { 
     if (actionContext == null) 
     { 
      throw new ArgumentNullException("actionContext"); 
     } 

     this.log.Error(string.Format("Unexpected error while executing {0}", this.BuildLogEntry(actionContext.ActionContext)), actionContext.Exception); 
     return TaskHelpers.Completed(); 
    } 

    Task<HttpResponseMessage> IActionFilter.ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
    { 
     if (actionContext == null) 
     { 
      throw new ArgumentNullException("actionContext"); 
     } 

     if (continuation == null) 
     { 
      throw new ArgumentNullException("continuation"); 
     } 

     if (!this.log.IsDebugEnabled) 
     { 
      // no point running at all if logging isn't currently enabled 
      return continuation(); 
     } 

     string logEntry = this.BuildLogEntry(actionContext); 
     IDisposable logContext = this.log.DebugTiming("Executing {0}", logEntry); 

     Task<string> requestContent; 
     if (actionContext.Request.Content != null) 
     { 
      requestContent = actionContext.Request.Content.ReadAsStringAsync().ContinueWith(requestResult => string.IsNullOrEmpty(requestResult.Result) ? "N/A" : requestResult.Result); 
     } 
     else 
     { 
      requestContent = TaskHelpers.FromResult("N/A"); 
     } 

     return requestContent.ContinueWith(
      requestResult => 
       { 
        this.log.DebugFormat("{0}, Request = {1}", logEntry, requestResult.Result); 

        return continuation() 
         .ContinueWith(t => 
          { 
           Task<string> responseContent; 
           if (t.IsCompleted && t.Result.Content != null) 
           { 
            responseContent = t.Result.Content.ReadAsStringAsync().ContinueWith(responseResult => string.IsNullOrEmpty(responseResult.Result) ? "N/A" : responseResult.Result); 
           } 
           else 
           { 
            responseContent = TaskHelpers.FromResult("N/A"); 
           } 

           return responseContent.ContinueWith(
            responseResult => 
             { 
              using (logContext) 
              { 
               this.log.DebugFormat("{0}, Status Code: {1}, Response = {2}", logEntry, t.Result.StatusCode, responseResult.Result); 
              } 

              return t.Result; 
             }); 
          }).Unwrap(); 
       }).Unwrap(); 
    } 

    /// <summary> 
    /// Builds log data about the request. 
    /// </summary> 
    /// <param name="actionContext">Data associated with the call</param> 
    private string BuildLogEntry(HttpActionContext actionContext) 
    { 
     string route = actionContext.Request.GetRouteData().Route.RouteTemplate; 
     string method = actionContext.Request.Method.Method; 
     string url = actionContext.Request.RequestUri.AbsoluteUri; 
     string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName; 
     string actionName = actionContext.ActionDescriptor.ActionName; 

     return string.Format("{0} {1}, route: {2}, controller:{3}, action:{4}", method, url, route, controllerName, actionName); 
    } 
} 

、あなたが合うものは何でもしてILog実装を置き換えることができます。 ILog.DebugTimingは、ストップウォッチを使用して各コールの経過時間を取得する拡張メソッドです。

編集: この投稿Get the IP address of the remote hostには、リモート発信者のIPアドレスを取得する方法の詳細があります。

乾杯、 ディーン

+0

あなたが作品を送っリンク: プライベート文字列GetClientIp(HttpRequestMessageリクエスト) \t \t { \t \t \tは(request.Properties.ContainsKey( "MS_HttpContext"))であれば \t \t \t {(MS_HttpContextWrapper)request.Properties ["MS_HttpContext"])。Request.UserHostAddress; {0} {0}}}}}} \t \t \t} \t \t \t IF(request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name)) \t \t \t { \t \t \t \t RemoteEndpointMessagePropertyプロップ; \t \t \t \t prop =(RemoteEndpointMessageProperty)request.Properties [RemoteEndpointMessageProperty.Name]; \t \t \t \t return prop.Address; \t \t \t} \t \t \t return null; \t \t} – maxfridbe

+0

マイクの答えがより良い選択であるように思えます。実際のロギング実装や、必要に応じて組み込みのWeb APIログフレームワークを注入することができます(したがって、労力が倍増するのを防ぎます)。 – Lex

+0

「ITraceWriter」ビットを調査しましたが、開始タイミングと終了タイミングを相関させることは非常に難しいように見えました。私たちは、上記のアプローチがより簡単であると判断しました。 –