我使用HttpClient向我的API项目发送请求,问题是GetFromJsonAsync方法无法解析响应JSON,但是如果我首先使用GetAsync方法获得响应,然后对其执行ReadFromJsonAsync,它将成功地解析JSON,为什么呢?
此代码不起作用:
public async Task<OperationResult<LoginNextStep>> SearchByEmailOrPhone(string emailOrPhone)
{
// This fails to parse the response body
var result = await _client.GetFromJsonAsync<ApiResult<OperationResult<LoginNextStep>>>
($"api/user/searchbyemailorphone/{emailOrPhone}", _jsonOptions);
return result.Data;
}这一次是:
public async Task<OperationResult<LoginNextStep>> SearchByEmailOrPhone(string emailOrPhone)
{
var result = await _client.GetAsync($"api/user/searchbyemailorphone/{emailOrPhone}");
// But this one works, with the same JSON
var jsonResult = await result.Content.ReadFromJsonAsync
<ApiResult<OperationResult<LoginNextStep>>>(_jsonOptions);
return jsonResult.Data;
}这是传递到方法中的_jsonOptions (通过构造函数注入类):
services.AddSingleton(new JsonSerializerOptions
{
Converters = { new JsonStringEnumConverter() },
PropertyNameCaseInsensitive = true
});编辑:
我忘了说,这只发生在从API返回的特定JSON中,我的意思是它与ApiResutl的类型相同,但是由于一些奇怪的原因它无法解析它,在我的API项目中,我使用AspNetCoreRateLimit包来抑制垃圾邮件请求,在这个包中,如果它决定删除一个请求,它默认会返回一行文本,但是我可以覆盖它,当它删除一个请求时,我添加了我自己的返回类型,并且它是一个ApiResult,它是我的API的所有端点中的默认返回类型,(因此,我希望该包返回与其他端点相同的结果,其状态代码为429,以指示TooManyRequests)。
这是在删除垃圾邮件请求时覆盖的返回类型:
public class CustomIpRateLimitMiddleware : IpRateLimitMiddleware
{
public CustomIpRateLimitMiddleware(RequestDelegate next, IProcessingStrategy processingStrategy,
IOptions<IpRateLimitOptions> options, IIpPolicyStore policyStore, IRateLimitConfiguration config,
ILogger<IpRateLimitMiddleware> logger) : base(next, processingStrategy, options, policyStore, config, logger)
{
}
public override async Task ReturnQuotaExceededResponse(HttpContext httpContext, RateLimitRule rule,
string retryAfter)
{
var result = new ApiResult
{
IsSuccessful = false,
MetaData = new MetaData
{
ApiStatusCode = ApiStatusCode.TooManyRequests,
Message = "You sent too many requests!!!"
}
};
var jsonOptions = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter() } };
var jsonResult = JsonSerializer.Serialize(result, jsonOptions);
httpContext.Response.Headers["Retry-After"] = retryAfter;
httpContext.Response.StatusCode = (int)ApiStatusCode.TooManyRequests;
httpContext.Response.ContentType = "application/json";
await httpContext.Response.WriteAsync(jsonResult);
//return base.ReturnQuotaExceededResponse(httpContext, rule, retryAfter);
}
}为了产生这个问题,首先我手动尝试垃圾邮件,API会扼杀我的请求:

然后这是作为字符串的响应体,它与上面的图片相同:

ReadFromJsonAsync可以解析JSON:

但是GetFromJsonAsync的同一个请求失败了,它抛出一个HttpRequestException异常,(我想我昨天做了同样的事情,它会抛出一个像CouldNotParseJson这样的异常到ApiResult类型):

例外细节:
System.Net.Http.HttpRequestException HResult=0x80131500 Message=Response状态代码并不表示成功: 429 (请求太多)。System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() at System.Net.Http.Json.HttpClientJsonExtensions.d__13'1.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() Source=System.Net.Http StackTrace (在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task任务)在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task任务)在System.Runtime.CompilerServices.TaskAwaiter'1.GetResult() at Shop.UI.Services.Users.UserService.d__14.MoveNext() in D:\VS Projects\Didikala\src\Shop\Shop.Presentation\Shop.UI\Services\Users\UserService.cs:line 99 这个异常最初被抛出在这个调用堆栈: System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() System.Net.Http.Json.HttpClientJsonExtensions.GetFromJsonAsyncCore(System.Threading.Tasks.Task,System.Text.Json.JsonSerializerOptions,( System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Shop.UI.Services.Users.UserService.SearchByEmailOrPhone(string) in UserService.cs )
似乎只有在响应成功时,GetFromJsonAsync才会尝试解析JSON,并且由于这个原因而失败,是否有任何方法让GetFromJsonAsync解析JSON响应,不管它是否成功?或者我只需分两步完成,即第一步GetAsync,然后用ReadFromJsonAsync解析它
发布于 2022-06-28 10:44:35
GetFromJsonAsync调用EnsureSuccessStatusCode,因此它需要200-299之间的状态代码。另一方面,ReadFromJsonAsync没有。
您的消息具有429状态,因此失败。
如果你想的话,你可以自己写分机。
public async Task<T> GetFromJsonAsync(string requestUri, JsonSerializerOptions options, CancellationToken cancellationToken = default)
{
using (var response = client.GetAsync(requestUri, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
{
var jsonResult = await result.Content.ReadFromJsonAsync<T>(_jsonOptions, cancellationToken);
return jsonResult;
}
}https://stackoverflow.com/questions/72769971
复制相似问题