【发布时间】:2020-12-09 16:39:31
【问题描述】:
我正在对我在 Xamarin.Forms 4.8 中创建的 ASP.NET Core Web API 执行一个简单的 GET 请求。为此,我使用以下代码:
public async Task<Result<bool>> GetSomeResult()
{
var client = service.Client;
HttpResponseMessage response = null;
try
{
response = await client.GetAsync(new UriHelper(endpoint, "someEndpoint")).ConfigureAwait(false);
response.EnsureSuccessStatusCode(); // will throw a exception on a non-success status code
return await response.Content.ReadAsAsync<bool>().ConfigureAwait(false);
}
catch (Exception ex)
{
if (response?.StatusCode == HttpStatusCode.InternalServerError)
{
// !!! The error occurs in the next line !!!
SomeErrorClass id = await response.Content.ReadAsAsync<SomeErrorClass>().ConfigureAwait(false);
return new Result<bool>(SomeErrorClass.ToString());
}
return new Result<bool>(ex);
}
}
service 是一个单例,它被注入到周围类的构造函数中(通过 DryIoc)。这个service 是一个HttpClient 实例的包装器,它只是提供了一个配置HttpClient 的工具(以及在其配置发生变化时处理和替换实例)。因此,在配置之后,无论何时使用 service.Client,都会返回相同的 HttpClient 实例。代码是这样的:
public class ServiceConnection
{
private const string Localhost = "https://127.0.0.1";
private readonly PreferenceService preferences;
private readonly IHttpClientHandlerProvider handlerProvider;
public HttpClient Client { get; private set; }
public ServiceConnection(PreferenceService preferences, IHttpClientHandlerProvider handlerProvider)
{
this.preferences = preferences;
this.handlerProvider = handlerProvider;
Client = CreateClient();
}
private HttpClient CreateClient()
{
var handler = new TimeoutHandler()
{
DefaultTimeout = TimeSpan.FromSeconds(10),
InnerHandler = handlerProvider?.GetHandler(opt =>
{
opt.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
opt.UseDefaultCredentials = true;
opt.AllowAutoRedirect = true;
})
};
Uri.TryCreate($"{preferences.Server ?? Localhost}/api/", UriKind.Absolute, out var baseAddress);
var client = new HttpClient(handler, true)
{
BaseAddress = baseAddress,
Timeout = TimeSpan.FromSeconds(20),
};
client.DefaultRequestHeaders.Add(CustomHttpHeaders.DeviceId, preferences.UUID);
return client;
}
public void RefreshConnection()
{
Client?.Dispose();
Client = CreateClient();
}
}
问题是我尝试从HttpResponseMessage 读取HttpContent 的行。每当我调用它时,我都会收到 System.ObjectDisposedExceptionsaying '无法访问已处置的对象。
对象名称:'System.Net.Http.StreamContent'。'。
我已经尝试将HttpClient 的disposeHandler 参数设置为true 和false,因为我在互联网上看到一些人建议这样可以解决问题,但我没有运气所以远。
【问题讨论】:
-
内容还是流?您的代码已经从网络流中读取了所有内容,因此无法再次从中读取。 NetworkStream 由 服务器 控制,不能只是重启
-
尝试两次读取和反序列化相同的内容,作为两个不同的类,即使有可能也是浪费。内容只需阅读一次。之后,可以使用您想要的任何反序列化器对实际内容进行反序列化
-
完全不扔会更好(而且更快)。不要调用
EnsureSuccessStatusCode(),而是检查响应的状态。现在您正在使用异常进行流控制,此时if可以工作 -
从docs"在.NET Framework和.NET Core 2.2及更早版本中,如果Content不为null,该方法也会调用Dispose释放托管和非托管资源。 "
-
顺便说一句EnsureStatusCode disposes when it throws。所以是的,例外是原因
标签: c# xamarin xamarin.forms dotnet-httpclient idisposable