Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
385 views
in Technique[技术] by (71.8m points)

c# - How can I read http request body in netcore 3 more than once?

I have a netcore 3 API application that logs the incoming request and then passes it on to the controller action.

My code looks like this:

public RequestLoggingHandler(IHttpContextAccessor httpContextAccessor)
{
    _httpContextAccessor = httpContextAccessor;
}


protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequestLoggingRequirement requirement)
{
    try
    {
        var httpContext = _httpContextAccessor.HttpContext;
        var request = httpContext.Request;

        _repository = (ICleanupOrderRepository)httpContext.RequestServices.GetService(typeof(ICleanupOrderRepository));
        _cache = (IMemoryCache)httpContext.RequestServices.GetService(typeof(IMemoryCache));

        httpContext.Items["requestId"] = SaveRequest(request);

        context.Succeed(requirement);

        return Task.CompletedTask;
    }
    catch (Exception ex)
    {

        throw ex;
    }
}

private int SaveRequest(HttpRequest request)
{
    try
    {
        // Allows using several time the stream in ASP.Net Core
        var buffer = new byte[Convert.ToInt32(request.ContentLength)];
       request.Body.ReadAsync(buffer, 0, buffer.Length);

        var requestContent = Encoding.UTF8.GetString(buffer);
        var requestId = _repository.SaveRawHandlerRequest($"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {requestContent}");

        return requestId;
    }
    catch (Exception ex)
    {

        throw ex;
    }
}

However when this request is passed on to the Controller the request body is null.

Previously in Core2.x you could do

request.EnableRewind();

My understanding is this is now replaced with

httpContext.Request.EnableBuffering();

However, even with

httpContext.Request.EnableBuffering();

the request body is still null once the request body is read.

How can I get around this ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is a known issue on github.

A temp workaround is to pull out the body right after the call to EnableBuffering and then rewinding the stream to 0 and not disposing it:

public class RequestLoggingHandler : AuthorizationHandler<RequestLoggingRequirement>
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    public RequestLoggingHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, RequestLoggingRequirement requirement)
    {
        try
        {
            var httpContext = _httpContextAccessor.HttpContext;
            var request = httpContext.Request;
            request.EnableBuffering();

            httpContext.Items["requestId"] = SaveRequest(request);
            context.Succeed(requirement);

            return Task.CompletedTask;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    private int SaveRequest(HttpRequest request)
    {
        try
        {
            // Allows using several time the stream in ASP.Net Core
            var buffer = new byte[Convert.ToInt32(request.ContentLength)];
            request.Body.ReadAsync(buffer, 0, buffer.Length);
            var requestContent = Encoding.UTF8.GetString(buffer);
            var requestId = _repository.SaveRawHandlerRequest($"{request.Scheme} {request.Host}{request.Path} {request.QueryString} {requestContent}");

            request.Body.Position = 0;//rewinding the stream to 0
            return requestId;
        }
        catch (Exception ex)
        {

            throw ex;
        }
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...