如何在C#中连续调用API



我有一个程序,它进行web API调用并返回JSON响应。从该JSON响应中,我需要获得Self链接,并对该端点进行另一次调用,然后自动返回该JSON响应。

在我最初的请求之后,我可能需要重复这个过程2-3次才能到达我想要的最终终点。

来自第一个API调用的JSON响应

public void makeRequestCall()
{
//Making call with base API plus desired endpoint parameters
string url = Consts.getURL;
//iniatialize HttpClient, set credentials, and make call
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(Consts.getURL);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(Consts.Username + ":" + Consts.Password)));
HttpResponseMessage response = client.GetAsync(url).Result;

// Get the response and print it
if (response.IsSuccessStatusCode)
{
var callResult = response.Content.ReadAsStringAsync().Result;
//deserialize the JSON response
callResult = JsonConvert.DeserializeObject(callResult).ToString();

JObject jObject = JObject.Parse(callResult);
Console.WriteLine(callResult);       
}
else
{
Console.WriteLine(response.StatusCode);
}
//...
}

您可以使用一些包装来完成API请求。但让我们从头开始。

使用HttpClient的服务


class MyService
{
private readonly ILogger _logger;
private readonly string _username = "";
private readonly string _password = "";
private readonly HttpClient _client;
public MyService(HttpClient client, ILogger<MyService> logger)
{
_client = client;
_logger = logger;
// Setup your credentials & headers. 
// Do not store _password in plain text its just for demo purpose!
//
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(_username + ":" + _password)));
}
public async Task MakeRequestCallsAsync()
{
// Do your first request. In this case to a dummy API
//
var request1 = await ExecuteNextRequestAsync<object, ResponseObject>(null!, (input) =>
{
return "https://dummyjson.com/products";
});
// Do your second request with the result of your first one
//
var request2 = await ExecuteNextRequestAsync<ResponseObject, ResponseProduct>(request1, (input) =>
{
return "https://dummyjson.com/products/" + input.Products.ElementAt(0).Id;
});

// And so on just by using the response of a previous request...
//
}
private async Task<TOut> ExecuteNextRequestAsync<TIn, TOut>(TIn lastResponse, Func<TIn, string> factory)
{
var url = factory(lastResponse);
var response = await _client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var responseJson = await response.Content.ReadAsStringAsync();
_logger.LogInformation($"{responseJson}");
var responseObj = JsonSerializer.Deserialize<TOut>(responseJson);
return responseObj;
}
else
{
_logger.LogError($"{response.StatusCode}");
return default;
}
}
}

注册您的服务


此示例使用Microsoft.Extensions.Http.Polly为每个服务实现注册一个HttpClient文档

// In your `Startup.cs` or if you are using > NET 6 in your `Program.cs`
services.AddHttpClient<MyService>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5))  
.AddPolicyHandler(GetRetryPolicy());
services.AddScoped<MyService>();
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}

重要信息:MyService基于响应对象调用API,该响应对象可以手动设置,也可以从上一次调用的反序列化响应中使用。但是它总是使用相同的Authorization-报头。


在中可以找到一个工作的dotnetfiddle示例

最新更新