我正在使用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=回應狀態碼不表示成功:429(請求過多)。Source = System.Net.Http StackTrace:在 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() 在 System.Net.Http.Json.HttpClientJsonExtensions.d__13'1.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw( )
在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 在 System.Runtime.CompilerServices.TaskAwaiter'1.GetResult() 在 Shop.UI.Services。 D:\VS Projects\Didikala\src\Shop\Shop.Presentation\Shop.UI\Services\Users\UserService.cs:line 99 中的 Users.UserService.d__14.MoveNext()此例外最初是在此呼叫堆疊中引發的:System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() System.Net.Http.Json.HttpClientJsonExtensions.GetFromJsonAsyncCore(System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>, System.Text.Json.JsonSerializerOptions, System.Threading.CancellationToken) System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task) System.Runtime.CompilerServices.TaskAwaiter UserService.cs 中的 .HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() Shop.UI.Services.Users.UserService.SearchByEmailOrPhone(string)
似乎GetFromJsonAsync只有在回應成功時才嘗試決議 JSON,并且因此而失敗,有沒有辦法GetFromJsonAsync決議 JSON 回應,無論它是否成功?或者我只需要分兩步完成,即首先GetAsync然后用ReadFromJsonAsync?
uj5u.com熱心網友回復:
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://www.uj5u.com/caozuo/497160.html
標籤:C# json asp.net 核心 dotnet-httpclient
