【问题标题】:Xamarin Http Request Timeout IssueXamarin Http 请求超时问题
【发布时间】:2021-10-16 17:46:00
【问题描述】:

我有一个基于 Xamarin 的移动应用程序和一个基于 .Net Core 的 Web API。移动应用通过 HttpClient 使用 Web API 的方法。下面的代码是我调用任何 Web API 方法的基本方法,关键是我想设置一个超时,但无论我实现了什么都无法设置确切的超时值。尝试过 Timespan.FromSeconds() 或 TimeSpan.FromMilliseconds() 等。当客户端向 Web API 发出请求时,会显示一个加载器来锁定 UI,并在 API 响应后将其删除。一些客户给我的反馈是加载器永远显示并且请求永远不会结束。也许,服务器在这个特定时间无法访问,或者客户端的 Internet 连接中断等。我只想设置超时并中断请求并向客户端显示警报消息。当然,我用谷歌搜索并尝试了太多提到的但没有结果。如果有人可以帮助我,将不胜感激。

    public async Task<BaseResponseModel> Post(BasePostModel postModel)
        {
            var responseModel = new BaseResponseModel();
            var json = postModel.ToString();
            var jsonParam = new StringContent(json, Encoding.UTF8, "application/json");
            var isPosted = true;
            var clientHandler = new HttpClientHandler()
            {
                AllowAutoRedirect = true,
                
            };

            var url = GetURL(postModel.UrlKey);

            var settings = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
                MissingMemberHandling = MissingMemberHandling.Ignore,
                ContractResolver = new DefaultContractResolver(),
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            };

            var client = new HttpClient(clientHandler);
            //client.Timeout = TimeSpan.FromSeconds(10);
            //var cancellationTokenSource = new CancellationTokenSource();
            //cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(10));

            client.DefaultRequestHeaders.Add("Accept", "application/json");
            client.DefaultRequestHeaders.Add("X-Env", "MOBILE_API");
            AttachToken(ref client, responseModel.Id);

            try
            {
                if (Preferences.ContainsKey("UserJwtExprieDate"))
                {
                    var expiryDate = Preferences.Get("UserJwtExprieDate", null);
                    if (DateTime.Now > DateTime.Parse(expiryDate))
                    {
                        Preferences.Remove("UserJwtExprieDate");
                        Preferences.Remove("HomePageInformation");
                        int index = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack.Count - 1;
                        Page currPage = Xamarin.Forms.Application.Current.MainPage.Navigation.NavigationStack[index];
                        if (currPage as SigninForFactorOne != null)
                        {}
                        else
                        {
                            App.LogoutUser();
                        }    
                    }
                    else
                    {
                        var response = await client.PostAsync(url, jsonParam);
                        if (response.IsSuccessStatusCode)
                        {
                            string result = response.Content.ReadAsStringAsync().Result;
                            var resultModel = JsonConvert.DeserializeObject<BaseResponseModel>(result, settings);
                            if (resultModel.ErrorType == APIErrorTypes.NULL)
                            {
                                if (resultModel.IsSucceed)
                                {
                                    responseModel.Data = resultModel.Data;
                                }
                                else
                                {
                                    responseModel.Error = resultModel.Error;
                                }

                                responseModel.Message = resultModel.Message;
                            }
                            else
                            {
                                responseModel.Error = "Token Expried Date.";
                                Preferences.Remove("UserJwtExprieDate");
                                Preferences.Remove("HomePageInformation");
                                App.LogoutUser();
                            }
                        }
                        else
                        {
                            new AppException(new Exception("HTTP Client response is not succeed!"), responseModel.Id);
                            isPosted = false;
                        }
                    }
                }
                else
                {
                    var response = await client.PostAsync(url, jsonParam);
                    if (response.IsSuccessStatusCode)
                    {
                        string result = response.Content.ReadAsStringAsync().Result;
                        var resultModel = JsonConvert.DeserializeObject<BaseResponseModel>(result, settings);
                        if (resultModel.ErrorType == APIErrorTypes.NULL)
                        {
                            if (resultModel.IsSucceed)
                            {
                                responseModel.Data = resultModel.Data;
                            }
                            else
                            {
                                responseModel.Error = resultModel.Error;
                            }

                            responseModel.Message = resultModel.Message;
                        }
                        else
                        {
                            responseModel.Error = "Token Expried Date.";
                            Preferences.Remove("UserJwtExprieDate");
                            Preferences.Remove("HomePageInformation");
                            App.LogoutUser();
                        }
                    }
                    else
                    {
                        new AppException(new Exception("HTTP Client response is not succeed!"), responseModel.Id);
                        isPosted = false;
                    }
                }
               
            }
            catch (Exception ex)
            {
                new AppException(ex, responseModel.Id, 500, "anonymous.user", "Unable to post data to API!");
                isPosted = false;
            }
            finally
            {
                if (!isPosted)
                {
                    responseModel.Error = AppConfiguration.GetSystemMessage(contactYourSystemAdministratorMessage);
                    responseModel.Message = AppConfiguration.GetSystemMessage(contactYourSystemAdministratorMessage);
                }
            }

            return responseModel;
        }

【问题讨论】:

    标签: xamarin.forms timeout httprequest


    【解决方案1】:

    我已使用以下解决方案手动设置超时,效果很好。

    internal class TimeOutHandler : DelegatingHandler
    {
        private readonly TimeSpan TimeOut;
    
        public TimeOutHandler(TimeSpan timeOut) => TimeOut = timeOut;
    
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage req, CancellationToken ct)
        {
            using (var ctTimeOut = CancellationTokenSource.CreateLinkedTokenSource(ct))
            {
                ctTimeOut.CancelAfter(TimeOut);
    
                try
                {
                    return await base.SendAsync(req, ctTimeOut.Token);
                }
                catch (OperationCanceledException) when (!ct.IsCancellationRequested)
                {
                    throw new TimeoutException();
                }
            }
        }
    }
    

    如何使用

    var interval = TimeSpan.FromSeconds(10);
    var handler = new TimeOutHandler(interval)
    {
        InnerHandler = new HttpClientHandler()
    };
    
    var client = new HttpClient(handler);
    

    欲了解更多信息,请查看:https://thomaslevesque.com/2018/02/25/better-timeout-handling-with-httpclient/

    【讨论】:

    • 我明天会尝试这个解决方案,并会写出结果,感谢您的关注。
    • 工作就像一个魅力:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 2013-09-05
    • 2011-11-05
    • 2010-12-12
    相关资源
    最近更新 更多