joe*_*joe 6 .net c# asp.net .net-core asp.net-core
StringContent/HttpContent是一次性的,HttpRequestMessage我想知道请求是否在处理StringContent时被处理HttpRequestMessage,或者我是否需要两个单独的using,或者是否有更好的方法来处理这些?例如
var content = new StringContent("test");
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri))
{
requestMessage.Content = content;
var response = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)
这是否需要:
using(var content = new StringContent("test"))
{
using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, requestUri))
{
requestMessage.Content = content;
var response = await HttpClient.SendAsync(requestMessage).ConfigureAwait(false);
}
}
Run Code Online (Sandbox Code Playgroud)
(在撰写本文时,OP的问题对于他们是否指的是HttpRequestMessage或含糊不清HttpResponseMessage,所以我将描述两者)。
HttpRequestMessage.Dispose():
Content。HttpResponseMessage.Dispose():
response.Content.response.RequestMessage或HttpRequestMessage以任何其他方式。
HttpRequestMessage.Content任何一个。在完全发送完您的请求之前,您HttpRequestMessage不应该丢弃它(我相信在某些(罕见)情况下,即使请求的内容尚未发送完毕,您也会得到回复 - 就像使用外来传输编码方案时一样)或多部分请求) - 但通常最好假设所有涉及的对象的嵌套生命周期,所以 _if是完美的(事实并非如此),那么你会这样做:HttpClientHttpResponseMessageSystem.Net.Http
HttpResponseMessage.HttpRequestMessage.HttpClient....但是,当您处理父请求/响应消息时,内容的处理是隐式的(并且您可能也不应该调用HttpClient.Dispose),所以只需执行以下操作:
using (HttpClient httpClient = this.httpClientFactory.CreateHttpClient()) // Only dispose HttpClient instances created by IHttpClientFactory. *DO NOT DISPOSE* of other HttpClient instances unless you know what you're doing!
using (HttpContent reqContent = new StringContent("test")) // Disposing of this HttpContent is unnecessary (as it's disposed when `request` is disposed).
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, requestUri) { Content = reqContent })
using (HttpResponseMessage response = await httpClient.SendAsync(request).ConfigureAwait(false)) // Note there is no `using()` block for the HttpContent object, this is because we don't "own" the object, the HttpResponseMessage does.
{
String responseBody = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return responseBody;
}
Run Code Online (Sandbox Code Playgroud)
尽管记住HttpRequestMessage和HttpResponseMessage对象是分开的,所以你可以处理你的HttpRequestMessage但仍然返回HttpResponseMessage(反之亦然!)(尽管如果你处理了你不能返回Stream来自- 所以如果你需要返回一个你应该子类并包装返回的值,但不处理它,而是将其处理在子类的方法中。ResponseMessage.Content.ReadAsStream()HttpResponseMessageStreamStreamstreamHttpResponseMessageStreamDispose
public async Task<Stream> GetStreamAsync()
{
using( HttpClient httpClient = this.httpClientFactory.CreateHttpClient() )
using( HttpContent reqContent = new StringContent("test") )
using( HttpRequestMessage request = new HttpRequestMessage( HttpMethod.Post, requestUri) { Content = reqContent })
{
HttpResponseMessage response = await this.httpClient.SendAsync( request ).ConfigureAwait(false);
try
{
Stream stream = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return new StreamWithDependencies( stream, response ); // See `class StreamWithDependencies` below.
}
catch // <-- When returning an IDisposable you should only dispose of things in `catch`, not in a `finally`.
{
response.Dispose(); // <-- Doing this means `response` (and `response.Content` will always be disposed) *and* can optionally outlive the method's scope if it follows the happy-path.
throw; // <-- Don't swallow any exceptions, re-throw them (don't use `throw ex;` as that resets the StackTrace, always use either `throw;` (without a name) or throw a new exception with the caught exception passed as the `Exception.InnerException`.)
}
}
}
Run Code Online (Sandbox Code Playgroud)
下面是一个看起来像这样的示例class Stream2:要点是它代理Stream,并且它的Dispose方法将处理您告诉它的其他对象。
using System.Collections.Immutable;
using System.IO;
class StreamWithDependencies : Stream
{
private readonly Stream subject;
private readonly ImmutableList<IDisposable> disposeWith;
public StreamWithDependencies( Stream subject, params IDisposable[] disposeWith )
{
this.subject = subject ?? throw new ArgumentNullException(nameof(subject));
this.disposeWith = ( disposeWith ?? Array.Empty<IDisposable>() ).ToImmutableList();
}
protected override void Dispose(Boolean disposing)
{
if( disposing )
{
this.subject.Dispose();
foreach( IDisposable d in this.disposeWith )
{
d.Dispose();
}
}
base.Dispose(disposing);
}
public override Int32 Read(...) => this.subject.Read( ... ):
pubiic override Task<Int32> ReadAsync( ... ) => this.Subject.ReadAsync( ... );
// etc
// Only implement and forward methods for reading, no need to implement methods for writing.
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3623 次 |
| 最近记录: |