androidasynchronousxamarinhttpwebresponsewebexception

Unhandled Exception in Xamarin Android When Using HttpWebResponse


I have the following code:

public async Task<List<RobotViewModel>> GetBot(string token)
    {
        var menulist = new List<RobotViewModel>();
        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create("mysite/bot/abc/process/GetBot");
            request.Accept = "application/json";
            request.Method = "GET";
            request.Headers["Authorization"] = "Bearer " + token;
            var response = (HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false);
            if(response.StatusCode==HttpStatusCode.OK)
            {
                var encoding = ASCIIEncoding.UTF8;
                using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
                {
                    string responseText = reader.ReadToEnd();
                    menulist = JsonConvert.DeserializeObject<List<RobotViewModel>>(responseText);
                }
            }
        }
        catch(System.Net.WebException exc)
        {
            var response = (HttpWebResponse)exc.Response;
            switch(response.StatusCode)
            {
                case HttpStatusCode.InternalServerError:
                    {
                        _userRepo = await new Repository<User>().MakeDatabaseAsync();
                        var user = await _userRepo.Table.Where(p => p.LoggedIn).FirstOrDefaultAsync();
                        await Login(user.UserName, user.Password);
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("mysite/bot/abc/process/GetBot");
                        request.Accept = "application/json";
                        request.Method = "GET";
                        request.Headers["Authorization"] = "Bearer " + user.AccessToken;
                        response = (HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false);
                        if (response.StatusCode == HttpStatusCode.OK)
                        {
                            var encoding = ASCIIEncoding.UTF8;
                            using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
                            {
                                string responseText = reader.ReadToEnd();
                                menulist = JsonConvert.DeserializeObject<List<RobotViewModel>>(responseText);

                            }
                        }
                        break;
                    }
                default:
                    throw;
            }
        }
        catch(Exception exc)
        {

        }

        return menulist;
    }

this code is used in the following delegate:

    navigationView.NavigationItemSelected += async delegate
            {

                AndHUD.Shared.Show(this, "Please Wait", -1, AndroidHUD.MaskType.Clear);


                var botList = await client.GetBot(loggedInUser.AccessToken);
                if (botList.Count > 0)
                {
                    var botListMemory = await _botRepo.GetAllAsync();

                    foreach (var item in botList)
                    {
                        var bot =await _botRepo.Table.Where(p => p.Token == item.Token).FirstOrDefaultAsync();
                        if(bot==null)
                        await _botRepo.CreateAsync(new Robot
                        {
                            Name = item.Name,
                            Token = item.Token,
                            TokenUrl = item.TokenUrl,
                            UserId = loggedInUser.Id,
                            Description = item.Description
                        });
                        else
                        {
                            bot.Name = item.Name;
                            bot.Token = item.Token;
                            bot.TokenUrl = item.TokenUrl;
                            bot.UserId = loggedInUser.Id;
                            bot.Description = item.Description;
                            await _botRepo.UpdateAsync(bot);
                        }
                    }

                    AndHUD.Shared.ShowSuccess(this, "Success", MaskType.Clear, TimeSpan.FromSeconds(2));
                }
                else
                    AndHUD.Shared.ShowError(this, "Server Error", MaskType.Clear, TimeSpan.FromSeconds(2));

                SetData(botList, out myAdapter);
                expandableListView.SetAdapter(myAdapter);
            };

When Bearer token is expired the catch block throws an unhandled exception. when I rerun the program, every thing works fine because new Bearer token has been generated in catch block at previous application run.


Solution

  • There was many problems in the code:

    1. ConfigureAwait(false) should be used just in class library because it causes the current task to be processed by a thread from threadPool not the main thread...
    2. httpClient should be in using block to dispose it out of using block. So I changed GetBot Method as follows:

      public async Task<List<RobotViewModel>> GetBot(string token)
      {
          var menulist = new List<RobotViewModel>();
          using (var localClient = new HttpClient())
          {
              try
              {
                  localClient.MaxResponseContentBufferSize = 256000;
                  localClient.Timeout = TimeSpan.FromSeconds(40);
                  localClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                  localClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
                  var uri = new Uri("mySite/GetBot");
                  var response = await localClient.GetAsync(uri);
                  if (response.StatusCode == HttpStatusCode.OK)
                  {
                      var encoding = ASCIIEncoding.UTF8;
                      using (var reader = new System.IO.StreamReader(await response.Content.ReadAsStreamAsync(), encoding))
                      {
                          string responseText = reader.ReadToEnd();
                          menulist = JsonConvert.DeserializeObject<List<RobotViewModel>>(responseText);
                      }
                  }
              }
              catch (Exception ex)
              {
                  throw ex;
              }
          }
          return menulist;
      }
      

      and then used it in async delegate:

              navigationView.NavigationItemSelected += async delegate
              {
                  AndHUD.Shared.Show(this, "Please Wait", -1, AndroidHUD.MaskType.Clear);
      
                  var botList = new List<RobotViewModel>();
                  var cts = new CancellationTokenSource();
      
                  try
                  {
                      _userRepo = await new Repository<User>().MakeDatabaseAsync();
                      var user = await _userRepo.Table.Where(p => p.LoggedIn).FirstOrDefaultAsync();
                      botList = await client.GetBot(user.AccessToken);
                      if (botList.Count > 0)
                      {
                          foreach (var item in botList)
                          {
                              var bot = await _botRepo.Table.Where(p => p.Token == item.Token).FirstOrDefaultAsync();
                              if (bot == null)
                                  await _botRepo.CreateAsync(new Robot
                                  {
                                      Name = item.Name,
                                      Token = item.Token,
                                      TokenUrl = item.TokenUrl,
                                      UserId = loggedInUser.Id,
                                      Description = item.Description
                                  });
                              else
                              {
                                  bot.Name = item.Name;
                                  bot.Token = item.Token;
                                  bot.TokenUrl = item.TokenUrl;
                                  bot.UserId = loggedInUser.Id;
                                  bot.Description = item.Description;
                                  await _botRepo.UpdateAsync(bot);
                              }
                          }
                          SetData(botList, out myAdapter);
                          expandableListView.SetAdapter(myAdapter);
                          AndHUD.Shared.ShowSuccess(this, "Success", MaskType.Clear, TimeSpan.FromSeconds(2));
                      }
                      else
                      {
                          _userRepo = await new Repository<User>().MakeDatabaseAsync();
                          user = await _userRepo.Table.Where(p => p.LoggedIn).FirstOrDefaultAsync();
                          var loginResponse = await client.Login(user.UserName, user.Password);
                          botList = await client.GetBot(loginResponse.access_token);
                          if (botList.Count > 0)
                          {
                              foreach (var item in botList)
                              {
                                  var bot = await _botRepo.Table.Where(p => p.Token == item.Token).FirstOrDefaultAsync();
                                  if (bot == null)
                                      await _botRepo.CreateAsync(new Robot
                                      {
                                          Name = item.Name,
                                          Token = item.Token,
                                          TokenUrl = item.TokenUrl,
                                          UserId = loggedInUser.Id,
                                          Description = item.Description
                                      });
                                  else
                                  {
                                      bot.Name = item.Name;
                                      bot.Token = item.Token;
                                      bot.TokenUrl = item.TokenUrl;
                                      bot.UserId = loggedInUser.Id;
                                      bot.Description = item.Description;
                                      await _botRepo.UpdateAsync(bot);
                                  }
                              }
                              SetData(botList, out myAdapter);
                              expandableListView.SetAdapter(myAdapter);
                              AndHUD.Shared.ShowSuccess(this, "Success", MaskType.Clear, TimeSpan.FromSeconds(2));
                          }
                      }
                  }
                  catch (Exception ex)
                  {
                      if (ex is AggregateException)
                      {
                          AndHUD.Shared.ShowError(this, "IO Error", MaskType.Clear, TimeSpan.FromSeconds(2));
                      }
                      else
                          AndHUD.Shared.ShowError(this, "Unknown", MaskType.Clear, TimeSpan.FromSeconds(2));
                  }
              };
      

      Now Every thing Works fine! Thanks for your time!