Wednesday, December 7, 2016

Calls to Microsoft Graph client library hangs in ASP.Net web forms web application

Recently I faced with strange problem: when tried to use Microsoft Graph client library in ASP.Net web forms web application (tried to run it in Azure web site) code hang and Request timeout exception was thrown after request processing time reached timeout value. E.g. if we will use example which I showed in one of the previous posts (see Work with Azure AD via Microsoft Graph API):

   1: class Program
   2: {
   3:     static void Main(string[] args)
   4:     {
   5:         enumGroups();
   6:         Console.ReadKey();
   7:     }
   8:  
   9:     static async void enumGroups()
  10:     {
  11:         var graph = new GraphServiceClient(new AzureAuthenticationProvider());
  12:         try
  13:         {
  14:             var groups = await graph.Groups.Request().GetAsync();
  15:             foreach (var g in groups)
  16:             {
  17:                 Console.WriteLine(g.DisplayName);
  18:             }
  19:         }
  20:          catch (ServiceException x)
  21:         {
  22:             Console.WriteLine("Exception occured: {0}", x.Error);
  23:         }
  24:     }
  25: }

thread hang on line 16 when we perform actual call to graph API for retrieving groups:

   1: var groups = await graph.Groups.Request().GetAsync();

However the same code worked well in console application even if we would remove async/await from enumGroups method and would call client library synchronously. In ASP.Net web forms it is little bit more tricky. In order to make it work you need to make all methods up in the call stack asynchronous including page itself (see Using Asynchronous Methods in ASP.NET 4.5). I.e. in .aspx file add Async=”true” attribute to the Page directive:

   1: <%@ Page Async="true" ...

After that rewrite page method which calls Graph client library in async way:

   1: protected void Page_Load(object sender, EventArgs e)
   2: {
   3:     RegisterAsyncTask(new PageAsyncTask(Page_LoadAsync));
   4: }
   5:  
   6: private async Task Page_LoadAsync()
   7: {
   8:     await enumGroups();
   9: }

(if you have other methods in call stack between Page_LoadAsync and enumGroups you need to make them async as well). After that call to Microsoft Graph client library shouldn’t stuck anymore and should work as expected. There is also similar issue with ASP.Net MVC web applications: Application hang when executing AuthenticationContext.AcquireTokenAsync. Solution is also similar: you have to change MVC actions from sync to async. Exactly this article pointed me to the right direction for ASP.Net web forms, so big thanks to the author.

2 comments: