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<T>(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 如何在一个地方捕获每个响应的主要内容,如果未能解决你的问题,请参考以下文章
httpclient获取响应实体和信息的封装方法(解耦更新)