【问题标题】:HttpClient How to catch every response in one placeHttpClient 如何在一个地方捕获每个响应
【发布时间】:2020-03-10 08:25:08
【问题描述】:

我正在开发与 Web Api 2 Api 连接的 Xamarin.Forms 应用程序,所有请求和响应都与 HttClient 一起工作。这是我的代码:

我所有请求的类和 HttpClient 的定义

  public class DataStore : IDataStore<object>
    {
        HttpClient client;

        public DataStore()
        {
            client = new HttpClient()
            {
                BaseAddress = new Uri($"{App.Uri}")
            };

        }

我的请求之一示例:

   public async Task<User> GetProfileSetup()
        {
            try
            {
                if (CrossConnectivity.Current.IsConnected)
                {
                    string token = DependencyService.Get<ISharedFunctions>().GetAccessToken();

                    client.DefaultRequestHeaders.Clear();
                    client.DefaultRequestHeaders.Add("Accept", "application/json");
                    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);

                    var response = await client.GetAsync(@"api/User/GetProfilSetup");
                    if (response.IsSuccessStatusCode)
                    {
                        string jsonMessage;
                        using (Stream responseStream = await response.Content.ReadAsStreamAsync())
                        {
                            jsonMessage = new StreamReader(responseStream).ReadToEnd();
                        }
                        User user = JsonConvert.DeserializeObject<User>(jsonMessage);


                        return user;
                    }
                    else
                    {
                        var m = response.Content.ToString();
                        return null;
                    }

                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                string error = ex.Message;
                return null;

            }
        }

我的想法是在一个地方检查每个响应(响应状态代码)。我需要这个来抛出警报错误,刷新令牌等。有没有可能的方法?我想控制每个请求/响应。

【问题讨论】:

    标签: c# xamarin xamarin.forms httpclient dotnet-httpclient


    【解决方案1】:

    如果有人对此有问题,只需要实现自定义处理程序,谁将继承表单 DelegatingHandler。我的代码示例:

      public class StatusCodeHandler : DelegatingHandler
        {
            public StatusCodeHandler(HttpMessageHandler innerHandler) : base(innerHandler) { }
            public GetStatusCode GetStatusCode = new GetStatusCode();
            protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {
                HttpResponseMessage response = null;
                    response = await base.SendAsync(request, cancellationToken);
                    if (response.IsSuccessStatusCode)
                    {
                        return response;
                    }
                else
                { 
                    var status_code = (int)response.StatusCode;
                    GetStatusCode.GetResponseCode(status_code);
                }
                return response;
            }
    
         }
    

    【讨论】:

      【解决方案2】:

      这与 xamarin 无关,它是 OOP 中的抽象问题。您可以并且应该抽象 HttpClient 及其方法以删除所有样板文件。

      示例 - GetAsync&lt;T&gt;(url) 将检查连接,表单请求添加必要的标头,等待响应,检查响应状态,读取响应并最终返回反序列化的响应。这样,如果你想添加缓存层就更容易了。基本 OOP。

      抽象你的代码:

      public async Task<T> GetAsync(string url)
      {
          try
          {
              if (!CrossConnectivity.Current.IsConnected)
              {
                  // throw custom exception?
                  new NoNetworkException();
              }
              var token = DependencyService.Get<ISharedFunctions>().GetAccessToken();
              client.DefaultRequestHeaders.Clear();
              client.DefaultRequestHeaders.Add("Accept", "application/json");
              client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
              var response = await client.GetAsync(url);
              if (!response.IsSuccessStatusCode)
              {
                  // read response and throw for logging?
                  new InvaidResponseException();// custom exceptions makes it easier for catching
              }
              using (Stream responseStream = await response.Content.ReadAsStreamAsync())
              {
                  // there should be an async overload to read too
                  var jsonMessage = new StreamReader(responseStream).ReadToEnd();
                  return JsonConvert.DeserializeObject<T>(jsonMessage);
              }                
          }
          catch(NoNetworkException ex)
          {
              // handle
          }
          catch(InvaidResponseException ex)
          {
              // handle 
          }
      }
      

      【讨论】:

      • 我知道它不是 xamarin ,它是 HttpClient 的基础,但我不想在每个异步任务中检查响应状态并复制代码。每个响应只在一个地方捕获并采取行动
      • 以上代码应该在 DataStore 类中,并且应该在所有 http 调用中使用 DataStore 的单例对象。如果你想在一个地方做像烤面包这样的 UI 动作......你应该在 BaseViewModel 中创建方法并在 ViewModel 的每个捕获中调用它
      • 你有例子吗?
      • 你的意思是 GetAsync() 在每个 AsyncTask 中调用?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-05
      • 1970-01-01
      • 2016-07-21
      • 2021-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多