Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Web API审核日志_C#_Asp.net_Asp.net Web Api - Fatal编程技术网

C# Web API审核日志

C# Web API审核日志,c#,asp.net,asp.net-web-api,C#,Asp.net,Asp.net Web Api,我需要审核对Web API的日志调用,理想情况下,我希望使用一个属性,比如: [HttpPost, Auditing] public dynamic MyAPICall() 该属性应该能够在执行前后截获API调用,以便记录参数以及API调用运行的时间 有了MVC,我可以创建ActionFilterAttribute派生并覆盖OnActionExecuted和OnActionExecuting 在Web API世界中是否可能实现等效功能?我将使用消息处理程序而不是属性 publi

我需要审核对Web API的日志调用,理想情况下,我希望使用一个属性,比如:

    [HttpPost, Auditing]
    public dynamic MyAPICall()
该属性应该能够在执行前后截获API调用,以便记录参数以及API调用运行的时间

有了MVC,我可以创建ActionFilterAttribute派生并覆盖OnActionExecuted和OnActionExecuting


在Web API世界中是否可能实现等效功能?

我将使用消息处理程序而不是属性

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(); 
    }
}
公共类日志处理程序:DelegatingHandler
{
受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
日志请求(请求);
返回base.sendaync(请求,取消令牌).ContinueWith(任务=>
{
var response=task.Result;
对数响应(响应);
返回响应;
});
}
私有无效日志请求(HttpRequestMessage请求)
{
(request.Content??new StringContent(“”)。ReadAsStringAsync()。ContinueWith(x=>
{
Logger.Info(“{4:yyyy-MM-dd HH:MM:ss}{5}{0}请求[{1}]{2}-{3}”,request.GetCorrelationId(),request.Method,request.RequestUri,x.Result,DateTime.Now,用户名(请求));
});
}
专用无效日志响应(HttpResponseMessage响应)
{
var request=response.RequestMessage;
(response.Content??new StringContent(“”)。ReadAsStringAsync()。ContinueWith(x=>
{
Logger.Info(“{3:yyyy-MM-dd HH:MM:ss}{4}{0}响应[{1}]-{2}”,request.GetCorrelationId(),response.StatusCode,x.Result,DateTime.Now,用户名(请求));
});
}
私有字符串用户名(HttpRequestMessage请求)
{
var values=new List().AsEnumerable();
if(request.Headers.TryGetValues(“当前用户的自定义头”,out values)==false)返回“”;
返回值。First();
}
}

我想您会对Web API跟踪感兴趣。它允许您查看Web API的内部机制

在你的例子中,我假设你对动作的输入和输出特别感兴趣。因此,您可以像下面的示例一样对TraceWriter进行校正,以过滤掉冗余信息:

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
            }
        }
    }
}
公共类ActionAuditor:ITraceWriter
{
private const string TargetOperation=“ExecuteAsync”;
private const string targetoperator=“ReflectedHttpActionDescriptor”;
公共无效跟踪(HttpRequestMessage请求、字符串类别、TraceLevel、Action traceAction)
{
var rec=新跟踪记录(请求、类别、级别);
追踪反应(rec);
if(记录操作==TargetOperation&&rec.Operator==targetPeartor)
{
if(rec.Kind==TraceKind.Begin)
{
//记录操作的输入
}
其他的
{
//记录操作的输出
}
}
}
}

Http消息处理程序应该是一个很好的扩展点,用于此类目的。不过要小心,并发请求内容读取可能存在一些问题。例如,模型绑定器可能在
LoggingHandler
读取请求内容时尝试读取请求内容,但未能对模型进行反序列化。要防止此类问题,只需向LogRequestLoggingInfo方法添加Wait调用

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
                });
        }
    }
}
公共类日志处理程序:DelegatingHandler
{
受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
//记录请求信息
LogRequestLoggingInfo(请求);
//执行请求
返回base.sendaync(请求,取消令牌).ContinueWith(任务=>
{
var response=task.Result;
//提取响应日志信息,然后保存该信息
LogResponseLogginInfo(响应);
返回响应;
});
}
私有void LogRequestLoggingInfo(HttpRequestMessage请求)
{
if(request.Content!=null)
{
request.Content.ReadAsByteArrayAsync()
.ContinueWith(任务=>
{
var result=Encoding.UTF8.GetString(task.result);
//把它记录在某个地方
}).Wait();/!!!这是修复方法!!!
}
}
专用无效日志响应LogginInfo(HttpResponseMessage响应)
{
if(response.Content!=null)
{
response.Content.ReadAsByteArrayAsync()
.ContinueWith(任务=>
{
var responseMsg=Encoding.UTF8.GetString(task.Result);
//把它记录在某个地方
});
}
}
}

您可以阅读更多信息。

我开发了一个库,它允许您使用操作过滤器记录与ASP.NET Web API控制器的交互

它可以记录带有调用方信息、参数、输出、持续时间、异常等的操作方法调用

看一看

可以使用以下命令快速创建使用此库的示例项目:

> dotnet new -i Audit.WebApi.Template
> dotnet new webapiaudit

这件事发生在我身上。。。所以我真的很感激你的回答,它为我节省了很多时间。@k0stya你如何在你的
api
控制器中应用
LoggingHandler
?链接失效,这里有一个回程链接我如何分析日志?在sharepoint中创建仪表板并定义kpi列表?这只是捕获用于记录的信息。如何/记录什么,甚至如何查看日志的细节则是另一回事。与此问题无关的一个问题。@JasonMeckley如何在
api
控制器中使用
LoggingHandler
?此实现旨在记录请求/响应。如果您需要控制器中的记录器,请将另一个记录器传递给控制器,关于如何实现这一点,有多种选项。