波莉 - "无法访问已关闭的流"



我正在升级一个Xamarinapp toMAUI并且考虑了一些解耦的问题。在我有一个数据存储来处理所有对API的请求之前,现在我有一个服务,用于应用程序的每个部分,请求从HttpManager问题是,当策略重试时,它第一次工作,但在第二次重试时,它失败了,消息"无法访问已关闭的流">。搜索了一下,但没有找到修复方法。

我从viewModel中调用服务。

LoginViewModel.cs

readonly IAuthService _authService;
public LoginViewModel(IAuthService authService)
{
_authService = authService;
}
[RelayCommand]
private async Task Login()
{
...

var loginResponse = await _authService.Login(
new LoginDTO(QRSettings.StaffCode, Password, QRSettings.Token));
...
}

在服务中,我设置发送数据到HttpManager并处理响应

AuthService.cs

private readonly IHttpManager _httpManager;
public AuthService(IHttpManager manager)
{
_httpManager = manager;
}
public async Task<ServiceResponse<string>> Login(LoginDTO model)
{
var json = JsonConvert.SerializeObject(model);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await _httpManager.PostAsync<string>("Auth/Login", content);
...
}

在这里我发送请求。

HttpManager.cs

readonly IConnectivity _connectivity;
readonly AsyncPolicyWrap _retryPolicy = Policy
.Handle<TimeoutRejectedException>()
.WaitAndRetryAsync(3, _ => TimeSpan.FromSeconds(1), (exception, timespan, retryAttempt, context) =>
{
App.AppViewModel.RetryTextVisible = true;
App.AppViewModel.RetryText = $"Attempt number {retryAttempt}...";
})
.WrapAsync(Policy.TimeoutAsync(11, TimeoutStrategy.Pessimistic));
HttpClient HttpClient;
public HttpManager(IConnectivity connectivity)
{
_connectivity = connectivity;
HttpClient = new HttpClient();
}
public async Task<ServiceResponse<T>> PostAsync<T>(string endpoint, HttpContent content, bool shouldRetry = true)
{
...
// Post request
var response = await Post($""http://10.0.2.2:5122/{endpoint}", content, shouldRetry);
...
}
async Task<HttpResponseMessage> Post(string url, HttpContent content, bool shouldRetry)
{
if (shouldRetry)
{
// This is where the error occurs, in the PostAsync
var response = await _retryPolicy.ExecuteAndCaptureAsync(async token =>
await HttpClient.PostAsync(url, content, token), CancellationToken.None);
...
}
...
}

这是MauiProgram

...
private static MauiAppBuilder RegisterServices(this MauiAppBuilder builder)
{
...
builder.Services.AddSingleton<IHttpManager, HttpManager>();
builder.Services.AddSingleton<IAuthService, AuthService>();
return builder;
}

我不知道是什么问题…我尝试了各种尝试/捕获,试图在网上找到解决方案,但没有运气。第二次重试时,它总是给出错误

免责声明:在评论部分,我建议倒带底层流。那个建议是错误的,让我纠正一下。

TL;DR:您不能重用HttpContent对象,您需要重新创建它。


为了能够使用POST谓词执行重试尝试,您需要为每次尝试重新创建HttpContent有效负载。

有几种方法可以修复你的代码:

传递序列化字符串作为参数

async Task<HttpResponseMessage> Post(string url, string content, bool shouldRetry)
{
if (shouldRetry)
{
var response = await _retryPolicy.ExecuteAndCaptureAsync(async token =>
await HttpClient.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json"), token), CancellationToken.None);
...
}
...
}

传递要序列化的对象作为参数

async Task<HttpResponseMessage> Post(string url, object content, bool shouldRetry)
{
if (shouldRetry)
{
var response = await _retryPolicy.ExecuteAndCaptureAsync(async token =>
await HttpClient.PostAsync(url, JsonContent.Create(content), token), CancellationToken.None);
...
}
...
}
  • 这里我们将利用。net 5
  • 中引入的JsonContent类型。

传递要序列化的对象作为参数#2

async Task<HttpResponseMessage> Post(string url, object content, bool shouldRetry)
{
if (shouldRetry)
{
var response = await _retryPolicy.ExecuteAndCaptureAsync(async token =>
await HttpClient.PostAsJsonAsync(url, content, token), CancellationToken.None);
...
}
...
}
  • 这里我们利用了一个名为PostAsJsonAsync的扩展方法
    • 这是在HttpClientExtensions
    • 下引入的
    • 但现在它位于HttpClientJsonExtensions

最新更新