Web API request content empty

10,316

The request body stream is read and bound into parameters and as a result of binding, the stream has been positioned to the end. That is why it is coming as empty. If you seek to the beginning before request.Content.ReadAsStringAsync(), it should work. Instead of that, you can simply read the request body first before binding happens, some thing like this.

public class RequestAndResponseLoggerDelegatingHandler : DelegatingHandler
{
    public IDataAccess Data { get; set; }

    protected override async Task<HttpResponseMessage> SendAsync(
                            HttpRequestMessage request, 
                                 CancellationToken cancellationToken)
    {
        var started = DateTime.UtcNow;
        var requestContent = await request.Content.ReadAsStringAsync();

        var response = await base.SendAsync(request, cancellationToken);

        var responseContent = await response.Content.ReadAsStringAsync();
        await Log(started, request, response, requestContent, responseContent);
        return response;
    }

    private async Task Log(DateTime start, HttpRequestMessage request, 
                             HttpResponseMessage response, string requestContent, 
                                string responseContent)
    {
        var finished = DateTime.UtcNow;           
        var info = new ApiLogEntry(start, finished, requestContent, responseContent, 
                                        request, response);
        Data.Log(info);
    }
}
Share:
10,316
David Keaveny
Author by

David Keaveny

Updated on June 17, 2022

Comments

  • David Keaveny
    David Keaveny almost 2 years

    I have a DelegatingHandler implementation to log request/response content:

    public class RequestAndResponseLoggerDelegatingHandler : DelegatingHandler
    {
        public IDataAccess Data { get; set; }
    
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var started = DateTime.UtcNow;
            var response = await base.SendAsync(request, cancellationToken);
            await Log(started, request, response);
            return response;
        }
    
        private async Task Log(DateTime start, HttpRequestMessage request, HttpResponseMessage response)
        {
            var finished = DateTime.UtcNow;
            var requestContent = await request.Content.ReadAsStringAsync();
            var responseContent = await response.Content.ReadAsStringAsync();
            var info = new ApiLogEntry(start, finished, requestContent, responseContent, request, response);
            Data.Log(info);
        }
    }
    

    but for some reason requestContent is coming up empty. request.Content.Length is confirming that there is content, it's just not being extracted.

    Any ideas?

  • Anatolii Humennyi
    Anatolii Humennyi about 7 years
    But after that the binding always returns null object because the stream was already read to the end. How to reset request stream to the beginning?
  • Sean Mahan
    Sean Mahan over 5 years
    There's a way to access the actual input stream form the request properties, shared here: stackoverflow.com/a/11902185/1108969