使用 HttpWebResponse 时 Xamarin Android 中未处理的异常

Unhandled Exception in Xamarin Android When Using HttpWebResponse

我有以下代码:

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;
    }

此代码用于以下委托:

    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);
            };

当 Bearer 令牌过期时,catch 块会引发未处理的异常。当我重新运行 程序时,一切正常,因为新的 Bearer 令牌已在先前应用程序 运行.

的 catch 块中生成

代码中有很多问题:

  1. ConfigureAwait(false) 应该只在 class 库中使用,因为它会导致当前任务由 threadPool 中的线程处理,而不是主线程...
  2. httpClient 应该在 using 块中将其从 using 块中释放出来。 所以我改变了 GetBot 方法如下:

    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;
    }
    

    然后在异步委托中使用它:

            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));
                }
            };
    

    现在一切正常!感谢您的宝贵时间!