0

I am using .NET Core Web API. I am working with some third party web api which I need to call in my Web API (so my .NET Core Web API is kind of wrapper on third party ones).

To get my result, I need to call more then one third party api using foreach loop. Details are as below:

  • First will be a Web API call which gives me result of around 4000 rows (each row is object of Id and value fields).

  • After that I need to loop through this 4000 rows and using each Id I need to call another API. On the result of this Web API I need to check some validation and return the valid ones.

I am able to make first Web API call successfully but when I do looping for another API call it gives me timeout error.

I have tried below things

1) making batches of 4000 rows and processing in batches.
2) Adding tasks in `foreach` loop and using `Task.WhenAll`

Example :

var batchSize = 50;
var returnData = new List<Order>();
foreach (var batchedItems in inventoriesList.Batch(batchSize)) //4000 rows 
{   
    var tasks = new List<Task<Order>>();
    foreach (var item in batchedItems)
    {
        tasks.Add(GetOrder(item.Value)); //call to another api
    }

    foreach (var task in await Task.WhenAll(tasks))
    {
        returnData.Add(task);       
    }
}

private async Task<Order> GetOrder(string id)
{       
    var order = await GetAsync<Order>(api-url);
    if (order != null
        && order.IsAvailable == false
        && ValidateOrder(order)))
    {
        isValidOrder = true;
    }
    return isValidOrder == true ? order : null;
}

I have tried with LINQ as well rather then doing foreach loop for second API call. Like below,

tasks = batchedInventories.Select(t => GetOrder(t.Value));
var result = await Task.WhenAll(tasks);

I have also tried with increasing KeepAliveTimeout of Kestrel. But no luck. Could anybody suggest me correct and working way to do this?

Dale K
  • 25,246
  • 15
  • 42
  • 71
vibs
  • 115
  • 2
  • 14
  • 3
    I'd recommend showing your `GetAsync` code, and if my hunch is right, you might also need to read [this](https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/). Alternatively the API is throttling your many requests, or you're simply overloading it with too many requests. – ProgrammingLlama Nov 26 '18 at 01:32
  • 1
    yes, I am using "using" statement in GetAsync and creating new HttpClient for each request. I will try sharing single httpclient instance. – vibs Nov 26 '18 at 01:46
  • Just a quick question, I have HttpClientHandler (with cookiecontainer) , how should I use that with static httpclient? – vibs Nov 26 '18 at 03:31
  • Can you provide the exact error message, and the line of code it is occurring on. – Dale K Nov 26 '18 at 03:44
  • Before you start experimenting with code - did you actually estimated (or better yet tried with something like Fiddler) to send 4K requests to that service and see how long it takes? Sending so many requests in short amount of time will overwhelm almost all except the most powerful servers... – Alexei Levenkov Nov 26 '18 at 03:44
  • @Alexei, Have not tried with 4k yet. But using the code above even doing with 500 gives timeout error. – vibs Nov 26 '18 at 03:57
  • @Dale : it gives error like below when doing foreach for Task.WhenAll(){System.Net.Http.WinHttpException (0x80072EE2): The operation timed out at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Threading.Tasks.RendezvousAwaitable`1.GetResult() at System.Net.Http.WinHttpHandler.d__105.MoveNext()} – vibs Nov 26 '18 at 04:40
  • @John, I am not sure we can pass cookiecontainer to static HttpClient, is it feasible? – vibs Nov 26 '18 at 04:54
  • @vibs I've never needed cookies, but [this might help](https://stackoverflow.com/questions/35704788/c-sharp-how-to-pass-on-a-cookie-using-a-shared-httpclient). Note that you probably still want to throttle how many requests you make simultaneously, of course. – ProgrammingLlama Nov 26 '18 at 04:58
  • https://dotnetcodr.com/2013/01/04/timeout-exceptions-with-asyncawait-in-net4-5-mvc4-with-c/ – CodeConstruct Nov 26 '18 at 05:39

1 Answers1

0

I managed to resolve this error by creating static HttpClient for GetAsync method rather then creating instance for each request. Thanks a ton to John !!

I initialized static HttpClient in constructor with cookiecontainer. Reference : Using httpclient throughout methods without losing session and cookies

vibs
  • 115
  • 2
  • 14