阅读HttpContent

时间:2016-03-09 04:26:18

标签: c# http asp.net-web-api streaming message-handlers

我想在Visual C#Web API程序中记录有关HttpRequestMessage响应的信息。我想使用消息处理程序(继承自DelegatingHandler),如下所示:

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
{
    // log request.Method & request.RequestUri
    var result = await base.SendAsync(request, cancellationToken);
    // log first 100 chars of result.Content
    return result
}

问题是result.Content有时会很大,所以我想将它限制为仅打印前N个字符(大约50个)。

我尝试了什么:

  • 使用toString()并使用SubString将整个内容复制到字符串。这正是我想要的,但是将大量字符串读入内存然后只使用前几个字符似乎很浪费 - 我觉得必须有更好的方法。
  • 来自互联网的各种解决方案,可以读取字符但从流中删除它们。我需要按原样发送完整的流。

1 个答案:

答案 0 :(得分:0)

通过这种方式,您可以从流中复制所需的信息,并将响应传递到目前的位置。

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) {
    // log request.Method & request.RequestUri
    var response = await base.SendAsync(request, cancellationToken);
    // log first 100 chars of response.Content
    var N = 100;
    var first_100_Chars = await ReadFirstNCharsOfHttpContent(response.Content, N);

    return response;
}

private static async Task<string> ReadFirstNCharsOfHttpContent(HttpContent httpContent, int N = 100) {
    //get the content Stream
    var contentStream = await httpContent.ReadAsStreamAsync().ConfigureAwait(false);
    //How big is it
    var streamLength = contentStream.Length;
    // Get the size of the buffer to be read
    var bufferSize = (int)(streamLength > N ? N : (N > streamLength ? streamLength : N));
    var ms = new System.IO.MemoryStream(bufferSize);
    //copy only the needed length
    await contentStream.CopyToAsync(ms, bufferSize);

    // The StreamReader will read from the current 
    // position of the MemoryStream which is currently 
    // set at the end of the data we just copied to it.

    // We need to set the position to 0 in order to read 
    // from the beginning.
    ms.Position = 0;
    //reset content position just to be safe.
    contentStream.Position = 0;

    var sr = new System.IO.StreamReader(ms);
    var logString = sr.ReadToEnd();

    return logString;
}