如何在原始请求具有内容时克隆HttpRequestMessage?

Pra*_*bhu 12 .net c# rest http dotnet-httpclient

我正在尝试使用此答案中概述的方法克隆请求:https: //stackoverflow.com/a/18014515/406322

但是,如果原始请求包含内容,则会收到ObjectDisposedException.

你如何可靠地克隆HttpRequestMessage?

Car*_*s P 23

这应该做的伎俩:

    public static async Task<HttpRequestMessage> CloneHttpRequestMessageAsync(HttpRequestMessage req)
    {
        HttpRequestMessage clone = new HttpRequestMessage(req.Method, req.RequestUri);

        // Copy the request's content (via a MemoryStream) into the cloned object
        var ms = new MemoryStream();
        if (req.Content != null)
        {
            await req.Content.CopyToAsync(ms).ConfigureAwait(false);
            ms.Position = 0;
            clone.Content = new StreamContent(ms);

            // Copy the content headers
            if (req.Content.Headers != null)
                foreach (var h in req.Content.Headers)
                    clone.Content.Headers.Add(h.Key, h.Value);
        }


        clone.Version = req.Version;

        foreach (KeyValuePair<string, object> prop in req.Properties)
            clone.Properties.Add(prop);

        foreach (KeyValuePair<string, IEnumerable<string>> header in req.Headers)
            clone.Headers.TryAddWithoutValidation(header.Key, header.Value);

        return clone;
    }
Run Code Online (Sandbox Code Playgroud)

  • 所以在.NET 5中,它应该更改为类似`foreach (KeyValuePair&lt;string, object?&gt; option in req.Options)clone.Options.Set(new HttpRequestOptionsKey&lt;object?&gt;(option.Key), option.Value) ;` (3认同)

Dar*_*ler 6

如果在内容上调用LoadIntoBufferAsync,则可以保证内容在HttpContent对象内缓冲.剩下的唯一问题是读取流不会重置位置,因此您需要ReadAsStreamAsync并设置流Position = 0.

我的例子与卡洛斯的例子非常相似......

 private async Task<HttpResponseMessage> CloneResponseAsync(HttpResponseMessage response)
        {
            var newResponse = new HttpResponseMessage(response.StatusCode);
            var ms = new MemoryStream();

            foreach (var v in response.Headers) newResponse.Headers.TryAddWithoutValidation(v.Key, v.Value);
            if (response.Content != null)
            {
                await response.Content.CopyToAsync(ms).ConfigureAwait(false);
                ms.Position = 0;
                newResponse.Content = new StreamContent(ms);

                foreach (var v in response.Content.Headers) newResponse.Content.Headers.TryAddWithoutValidation(v.Key, v.Value);

            }
            return newResponse;
        }
Run Code Online (Sandbox Code Playgroud)

```