1

I'm using Microsoft Graph API library (C#) and wondering if anyone has experienced this:
Many of my graph API calls time out from time to time.
This can happen to any API call, from getting current user profile to getting sharepoint documents, and so on. I've tried updating Microsoft Graph API and dependent Nuget packages to the latest versions, but it doesn't help.

To clarify, this application is a Windows console application. On Azure side, it is registered as a native application. As a test application, it is a single-threaded application. No concurrency, race conditions involved. Code logic is as simple as

  1. User logs in.
  2. The program makes a Graph API call (shown in eg.1) to get user's profile and this API call times out.

eg 1.

var currentUser = graphClient.Me.Request().GetAsync().Result;

eg 2.

var site = _graphClient.Sites[SharePointSiteId].Request().GetAsync().Result;

The symptom is after a minute or two, it throws an AggregationException(because of TPL) which includes a TimeOutException.
No unauthorized exception.

I want to know what could be the possible cause and how I can avoid that.


UPDATE: Here's a screenshot when the exception happens. enter image description here


UPDATE 2: I've tried replacing all the API calls to use "await" directly to wait for results. because this example code is a console application. I put

static void Main(string[] args)
{
    // using Stephen Cleary's nuget package: Nito.AsyncEx.Tasks
    MainImp().WaitAndUnwrapException();
}

static async Task MainImp()
{
    // ...
    // Graph API calls

This exception is still thrown from this simple API call:

var currentUser = await graphClient.Me.Request().GetAsync();

An unhandled exception of type 'Microsoft.Graph.ServiceException' occurred in mscorlib.dll Additional information: Code: timeout

Here's the full call stack

at Microsoft.Graph.HttpProvider.d__19.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.HttpProvider.d__18.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.BaseRequest.d__35.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.BaseRequest.d__311.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Graph.UserRequest.<GetAsync>d__6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult() at SharePointConsoleApp.Program.d__14.MoveNext() in D:\TestProjects\SharePointConsoleApp\Program.cs:line 133 --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task) at SharePointConsoleApp.Program.Main(String[] args) in D:\TestProjects\SharePointConsoleApp\Program.cs:line 50 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()

detale
  • 12,482
  • 4
  • 41
  • 42
  • What application is using the API? Where are you calling from=>to? – tukan Jul 11 '19 at 05:39
  • MVC web application. calling the Graph API from server side (C#) – detale Jul 11 '19 at 06:32
  • 2
    Without a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) that clarifies your specific problem or additional details to highlight exactly what was done, it’s hard to reproduce the problem, allowing a better understanding of what is being asked. – Nkosi Jul 11 '19 at 08:57
  • 2
    Possible cause: deadlocks. How to avoid: avoid making blocking calls in async code. – Nkosi Jul 11 '19 at 08:58
  • More context is needed about where and how the shown code is invoked. – Nkosi Jul 11 '19 at 08:59
  • @Nkosi, more context info added. thanks! – detale Jul 11 '19 at 22:59
  • Could you do simple pings? To see if the endpoint is reachable at the time you are experiencing timeouts? – tukan Jul 12 '19 at 06:01
  • @tukan Both of the examples are a simply GET request. I guess it's equivalent to ping, unless you ping https://graph.microsoft.com/v1.0 to see if MS's graph API is available. – detale Jul 12 '19 at 07:10
  • Yes, I wanted the ping to see if the API is available for you. Why I'm asking is that it could be infrustructure problem not a programming one. – tukan Jul 12 '19 at 07:18
  • can you update your question to include the exact exceptions you get in full. Which will include a request-id? – Jeremy Thake MSFT Jul 12 '19 at 15:13
  • @JeremyThakeMSFT please advise where can i find the request-id when using this GraphClient object. – detale Jul 12 '19 at 16:40
  • It's probably dead locks due to blocking async calls. Replace you code with the `async` keyword all over, instead of using `.Result` and use `ConfigureAwait(false)`, similar to this: https://stackoverflow.com/questions/56594504/why-does-reading-from-pipe-block-the-process – Simon Mourier Jul 15 '19 at 06:28

3 Answers3

0

First of all if it's an application with user interaction you should never do blocking (.Wait() or .Result) calls on the main thread, this will lock-up your application for further user interaction.

So you need to start by using async code, this is a sample of an async Button_Click handler. It will give you a warning, but this seems to be one of the use-cases of an async void.

private async void Button_Click(object sender, RoutedEventArgs 
{
    var currentUser = await graphClient.Me.Request().GetAsync();
    // Presumably do something with the response
    labelUser.Text = currentUser.DisplayName;
}

Few days ago I found a nice video about common async/await mistakes

You seem to be talking about a console app running on windows.

As of C# 7.1 you can also have an public static Task Main(string[] args) as starting point. Then your application would look like this:

public static async Task Main(string[] args) {
  // Create the client here.....
  var graphClient = .....;
  // Await every call to the graphclient
  var currentUser = await graphClient.Me.Request().GetAsync();
  // Do something with the user

}
Stephan
  • 2,356
  • 16
  • 38
  • My work environment doesn't have C# 7.1 installed, but other than that, I updated all other code having async methods all the way to the Main method, and it still could time out. thanks though! – detale Jul 16 '19 at 15:24
  • It will also timeout if your program ends before the request is complete. Do you have a more complete sample of your code that is timing out? – Stephan Jul 16 '19 at 21:25
0

Maybe the reponse(payload) you get is very huge that while it processes the request times out? I had this issue frequently a while back while I was fiddling with graph api so i used pagination to limit the size/quantity of items sent back by it.

PrajwolCE
  • 53
  • 6
0

I've just experienced this and the cause was a corporate firewall was blocking traffic to graph.microsoft.com:443

This can be seen in wireshark as [TCP Retransmission]s after the initial request.

Unblocking this host resolved this issue for me.

ximon
  • 197
  • 3
  • 11