Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.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# 在.NET Core 3中记录请求有效负载_C#_Asp.net Core_.net Core 3.0 - Fatal编程技术网

C# 在.NET Core 3中记录请求有效负载

C# 在.NET Core 3中记录请求有效负载,c#,asp.net-core,.net-core-3.0,C#,Asp.net Core,.net Core 3.0,我最近将一个API升级到了.NETCore3,据我所知,升级后这个API就停止工作了 我想记录异常和通过请求体传入的json负载。此ExceptionLogger作为过滤器插入以全局处理错误: public class ExceptionLogger { private readonly IServiceScopeFactory _factory; public ExceptionLogger(IServiceScopeFactory factory) {

我最近将一个API升级到了.NETCore3,据我所知,升级后这个API就停止工作了

我想记录异常和通过请求体传入的json负载。此ExceptionLogger作为过滤器插入以全局处理错误:

public class ExceptionLogger
{
    private readonly IServiceScopeFactory _factory;

    public ExceptionLogger(IServiceScopeFactory factory)
    {
        _factory = factory;
    }   

    public async Task<Guid?> LogException(Exception ex)
    {
        using var scope = _factory.CreateScope();
        var accessor = scope.ServiceProvider.GetRequiredService<IHttpContextAccessor>();
        var displayUrl = accessor?.HttpContext?.Request?.GetDisplayUrl();
        var payload = await RetrievePayload(accessor, displayUrl);

        // ... code proceeds to log the exception, including the payload.
    }

    private async Task<string> RetrievePayload(IHttpContextAccessor accessor, string displayUrl)
    {
        accessor.HttpContext.Request.EnableBuffering();
        accessor.HttpContext.Request.Body.Seek(0, System.IO.SeekOrigin.Begin);
        using var sr = new System.IO.StreamReader(accessor.HttpContext.Request.Body);

        return await sr.ReadToEndAsync(); // The request body is always empty now....!
    }
}

公共类例外日志
{
私有只读读写器ViceScopeFactory\u工厂;
公共例外记录员(IServiceScope工厂)
{
_工厂=工厂;
}   
公共异步任务日志异常(异常ex)
{
使用var scope=_factory.CreateScope();
var accessor=scope.ServiceProvider.GetRequiredService();
var displayUrl=accessor?.HttpContext?.Request?.GetDisplayUrl();
var payload=await RetrievePayload(访问者,显示URL);
//…代码继续记录异常,包括有效负载。
}
专用异步任务检索有效负载(IHttpContextAccessor访问器,字符串显示URL)
{
accessor.HttpContext.Request.EnableBuffering();
accessor.HttpContext.Request.Body.Seek(0,System.IO.SeekOrigin.Begin);
使用var sr=new System.IO.StreamReader(accessor.HttpContext.Request.Body);
return wait sr.ReadToEndAsync();//请求正文现在总是空的。。。。!
}
}
accessor
有querystring和form参数,甚至
accessor.HttpContext.Request.ContentLength
也有一个值指示有效负载在那里。但是,
Request.Body
流是空的,即使我重置了光标位置


此时如何获取请求正文?以下是.net core 3.0的内容。如果您在为此配置之前多次尝试读取该主体,则它将在第一次读取时成功,而在后续读取时将失败。因此,您需要一个中间件来配置该主体以进行多次读取。如前所述,使用
request.EnableRewind()
标记请求时有一个变通方法,并且如前所述,您需要将对EnableRewind的任何调用更改为enablebuffer。因此,如果我们返回您的案例,您的错误处理程序应如下所示:

    public class ErrorLoggingMiddleware
{
    private readonly RequestDelegate next;

    public ErrorLoggingMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            context.Request.EnableBuffering(); // this part is crucial
            await this.next(context);
        }
        catch (Exception e)
        {

            var stream = context.Request.Body;
            stream.Seek(0, SeekOrigin.Begin);
            using var reader = new StreamReader(stream);
            var bodyString =  await reader.ReadToEndAsync();


            // log the error
        }
    }
}

或者,您可以将中间件分为两部分,首先用于第一个链接中提到的倒带。因为它必须在第一次读到正文之前运行。(需要先在StartUp.cs Configure中注册)然后您可以注册错误记录器middlerware,或者您也可以使用筛选器,因为我们已经为body启用了多次读取功能。

非常好,谢谢。它起作用了。我在中间件类中使用request.EnableReview,但无法使其正常工作。:)