HttpClient 如何在一个地方捕获每个响应

Posted

技术标签:

【中文标题】HttpClient 如何在一个地方捕获每个响应【英文标题】:HttpClient How to catch every response in one place 【发布时间】: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;

            
        

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

【问题讨论】:

【参考方案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 中调用?

以上是关于HttpClient 如何在一个地方捕获每个响应的主要内容,如果未能解决你的问题,请参考以下文章

QT 捕获事件(全局拦截)

httpclient获取响应实体和信息的封装方法(解耦更新)

返回类型与 Asynctask 不兼容

重新使用 HttpClient 但每个请求的超时设置不同?

如何在测试中模拟 Angular 4.3 httpClient 的错误响应

如何在 C# 中使用 HttpClient 读取 Web api 响应