我正在将 Xamarin 应用程序升级到 MAUI,并考虑将事物解耦一些。在我有一个处理对 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);
...
}
...
}
如果重要的话,这就是毛伊岛计划
...
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);
...
}
...
}
JsonContent
类型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
我只是把它放在那里,因为当我在 maui 中使用 post 对我用 azure 编写的 Web 服务进行 Web 服务调用时,遇到了这个流关闭错误。我正在将一些旧代码从 xamarin 转换为 maui。我把头发拔了几个小时。然后我查看了我正在使用的服务器名称和协议。我无意中使用了 http 作为协议。我改用 https,所有错误都消失了。