2012-09-06 16 views
8

necesito para auditar llamadas a mi Web API de registro, Lo ideal sería utilizar un atributo, algo así como:Web API de registro de auditoría

[HttpPost, Auditing] 
    public dynamic MyAPICall() 

El atributo debe ser capaz de interceptar la llamada a la API antes y después de la ejecución para registrar los parámetros y también, cuánto tardó la ejecución de la API en ejecutarse.

Con MVC podría crear un derivado de ActionFilterAttribute y anular OnActionExecuted y OnActionExecuting.

¿Es posible el equivalente en el mundo de la API web?

+1

http://stackoverflow.com/questions/10307333/asp-net-mvc-4-webapi-actionfilter-example – BNL

Respuesta

15

Utilizaría un manejador de mensajes en lugar de atributos.

public class LoggingHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     LogRequest(request); 

     return base.SendAsync(request, cancellationToken).ContinueWith(task => 
     { 
      var response = task.Result; 

      LogResponse(response); 

      return response; 
     }); 
    } 

    private void LogRequest(HttpRequestMessage request) 
    { 
     (request.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x => 
     { 
      Logger.Info("{4:yyyy-MM-dd HH:mm:ss} {5} {0} request [{1}]{2} - {3}", request.GetCorrelationId(), request.Method, request.RequestUri, x.Result, DateTime.Now, Username(request)); 
     }); 
    } 

    private void LogResponse(HttpResponseMessage response) 
    { 
     var request = response.RequestMessage; 
     (response.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x => 
     { 
      Logger.Info("{3:yyyy-MM-dd HH:mm:ss} {4} {0} response [{1}] - {2}", request.GetCorrelationId(), response.StatusCode, x.Result, DateTime.Now, Username(request)); 
     }); 
    } 

    private string Username(HttpRequestMessage request) 
    { 
     var values = new List<string>().AsEnumerable(); 
     if (request.Headers.TryGetValues("my-custom-header-for-current-user", out values) == false) return "<anonymous>"; 

     return values.First(); 
    } 
} 
+0

¿cómo puedo analizar esos registros? crear paneles y definir la lista kpi en sharepoint? –

+4

esto simplemente captura la información para el registro. los detalles de cómo/qué se registra o incluso cómo ver los registros es una cuestión diferente. Uno que es independiente de este problema. –

+0

@JasonMeckley ¿Cómo se hace uso de 'LoggingHandler' en su' api'' controller'? – uikrosoft

7

¿Ha consultado el servicio de búsqueda de la API web?

http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api

+0

Me encontré con un error con 'ITraceWriter' y Thread.CurrentPrincipal, así que no usé el oyente. [Link] (http://stackoverflow.com/questions/11870806/httpmessagehandler-reading-content) –

+0

Lo tengo .. . Parece que el error se resolvió aunque? –

+0

ITraceWriter rompió mi proyecto cuando intenté instalarlo, no lo recomiendo. Desinstaló el archivo de ensamblaje, por lo que si alguien quiere probarlo, ¡asegúrese de hacer una copia de seguridad de su proyecto! – rtp

5

creo que le interesará a echar un vistazo a la API Web trazado http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api. Le permite ver el mecanismo interno de la API web.

En su caso, supongo que está particularmente interesado en lo que es la entrada y salida de acciones. Por lo que puede el derecho de su TraceWriter como siguiente ejemplo para filtrar la información redundante:

public class ActionAuditor : ITraceWriter 
{ 
    private const string TargetOperation = "ExecuteAsync"; 
    private const string TargetOpeartor = "ReflectedHttpActionDescriptor"; 

    public void Trace(HttpRequestMessage request, string category, TraceLevel level, Action<TraceRecord> traceAction) 
    { 
     var rec = new TraceRecord(request, category, level); 
     traceAction(rec); 

     if (rec.Operation == TargetOperation && rec.Operator == TargetOpeartor) 
     { 
      if (rec.Kind == TraceKind.Begin) 
      { 
       // log the input of the action 
      } 
      else 
      { 
       // log the output of the action 
      } 
     } 
    } 
} 
15

Http controlador de mensajes debe ser un buen punto extensible para tales fines. Sin embargo, tenga cuidado, puede haber algunos problemas con la lectura de contenido de solicitud concurrente. Por ejemplo, Model Binder puede intentar leer el contenido solicitado mientras LoggingHandler lo está leyendo y no puede deserializar un modelo. Para evitar estos problemas solo agregue Wait call al método LogRequestLoggingInfo.

public class LoggingHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     // Log the request information 
     LogRequestLoggingInfo(request); 

     // Execute the request 
     return base.SendAsync(request, cancellationToken).ContinueWith(task => 
     { 
      var response = task.Result; 
      // Extract the response logging info then persist the information 
      LogResponseLoggingInfo(response); 
      return response; 
     }); 
    } 

    private void LogRequestLoggingInfo(HttpRequestMessage request) 
    { 
     if (request.Content != null) 
     { 
      request.Content.ReadAsByteArrayAsync() 
       .ContinueWith(task => 
        { 
         var result = Encoding.UTF8.GetString(task.Result); 
         // Log it somewhere 
        }).Wait(); // !!! Here is the fix !!! 
     } 
    } 

    private void LogResponseLoggingInfo(HttpResponseMessage response) 
    { 
     if (response.Content != null) 
     { 
      response.Content.ReadAsByteArrayAsync() 
       .ContinueWith(task => 
       { 
        var responseMsg = Encoding.UTF8.GetString(task.Result); 
        // Log it somewhere 
       }); 
     } 
    } 
} 

Puedes leer más sobre esto here.

+0

Me pasó a mí ... Así que realmente aprecio tu respuesta, me ahorró mucho tiempo. –

+0

+1 para obtener exactamente lo que necesitaba – raider33

+0

@ k0stya ¿cómo aplica el 'LoggingHandler' en su' api'' controller'? – uikrosoft

2

He trabajado en una biblioteca que le permite registrar las interacciones con los controladores de API web ASP.NET mediante el uso de filtros de acción.

Puede grabar llamadas al método de acción con información del llamante, argumentos, salida, duración, excepciones y más.

Eche un vistazo a Audit.WebApi.

Cuestiones relacionadas