在 xamarin 表单中的 api 请求的一处处理异常
Handle Exception at one place for api request in xamarin forms
我正在处理 Xamarin 表单,我需要在整个项目中发送大量 API 请求。我制作了一个全局 HTTP 客户端对象并在任何地方使用它。当 Internet 关闭或找不到服务器时,如何处理 HttpRequestException。我正在考虑在一个地方处理这个异常,这样我就不会在数百个地方重复代码。我应该在哪里以及如何做。在 Xamarin.Forms 中,我读到我们无法全局处理异常。我想在一个地方处理所有异常并从那里显示一个错误页面。
服务Class
public partial class Service
{
private string BaseUrl { get; set; }
private string AccessToken { get; set; }
private static HttpClient Client = new HttpClient();
public Service()
{
}
public Service(string BaseUrl)
{
this.BaseUrl = BaseUrl;
}
public Service(string BaseUrl, string AccessToken)
{
this.BaseUrl = BaseUrl;
this.AccessToken = AccessToken;
}
}
}
Api消费方式之一
public async Task<bool> ExternalLogin(string email)
{
bool UserAlreadyRegistered = false;
bool IsUserRegistered = true;
var request = new HttpRequestMessage()
{
RequestUri = new Uri(this.BaseUrl + "api/Account/UserInfo"),
Method = HttpMethod.Get,
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var UserInfo = await Client.SendAsync(request);
if (UserInfo.IsSuccessStatusCode)
{
var response = await UserInfo.Content.ReadAsStringAsync();
var authenticationTicket = JsonConvert.DeserializeObject<dynamic>(response);
if (authenticationTicket.Value<bool>("HasRegistered"))
{
UserAlreadyRegistered = true;
}
}
if (!UserAlreadyRegistered)
{
request = new HttpRequestMessage()
{
RequestUri = new Uri(this.BaseUrl + "api/Account/RegisterExternal"),
Method = HttpMethod.Post,
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var content = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string> ("Email", email)
});
request.Content = content;
var authenticateResponse = await Client.SendAsync(request);
if (!authenticateResponse.IsSuccessStatusCode)
{
IsUserRegistered = false;
}
}
return IsUserRegistered;
}
EvZ Ans 后更新
调用扩展方法:
string result = await Task.Run(() => new Service(Settings.BaseUrl, Settings.AccessToken).Register(Model)).ExecuteAsyncOperation();
扩展方法:
public static class TaskExtensions
{
public static async Task<T> ExecuteAsyncOperation<T>(this Task<T> operation)
{
try
{
return await operation;
}
catch
{
return default(T);
}
}
}
扩展您的服务以获得以下方法(根据您的需要):
async Task<T> Post<T>(string url, object body)
async Task<T> Get<T>(string url)
这些方法中的每一个都应该得到一个 HttpResponseMessage
,您应该检查它是成功还是失败。
此外,您可以引入一个 MyApi
class,它将以下面的方式使用您的 Service
class 中的方法:
async AuthenticationResult Authenticate() =>
await service.Post("http://myapi.com/token", new AuthenticationRequest { Username = "x", Password = "xxx"});
P.S.: 请注意 Service
是一个非常糟糕的命名。完全不清楚 Service
class 负责什么。
P.S.S.: 或者,您可以为 Task
创建一个扩展方法来包装所有 api 请求并进行一次 try / catch。
简单示例:
public static class TaskExtensions
{
public static async Task<T> ExecuteAsyncOperation<T>(this Task<T> operation)
{
try
{
return await operation;
}
catch{ }
}
}
var token = await apiService.Authenticate(string username, string password).ExecuteAsyncOperation();
我正在处理 Xamarin 表单,我需要在整个项目中发送大量 API 请求。我制作了一个全局 HTTP 客户端对象并在任何地方使用它。当 Internet 关闭或找不到服务器时,如何处理 HttpRequestException。我正在考虑在一个地方处理这个异常,这样我就不会在数百个地方重复代码。我应该在哪里以及如何做。在 Xamarin.Forms 中,我读到我们无法全局处理异常。我想在一个地方处理所有异常并从那里显示一个错误页面。
服务Class
public partial class Service
{
private string BaseUrl { get; set; }
private string AccessToken { get; set; }
private static HttpClient Client = new HttpClient();
public Service()
{
}
public Service(string BaseUrl)
{
this.BaseUrl = BaseUrl;
}
public Service(string BaseUrl, string AccessToken)
{
this.BaseUrl = BaseUrl;
this.AccessToken = AccessToken;
}
}
}
Api消费方式之一
public async Task<bool> ExternalLogin(string email)
{
bool UserAlreadyRegistered = false;
bool IsUserRegistered = true;
var request = new HttpRequestMessage()
{
RequestUri = new Uri(this.BaseUrl + "api/Account/UserInfo"),
Method = HttpMethod.Get,
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var UserInfo = await Client.SendAsync(request);
if (UserInfo.IsSuccessStatusCode)
{
var response = await UserInfo.Content.ReadAsStringAsync();
var authenticationTicket = JsonConvert.DeserializeObject<dynamic>(response);
if (authenticationTicket.Value<bool>("HasRegistered"))
{
UserAlreadyRegistered = true;
}
}
if (!UserAlreadyRegistered)
{
request = new HttpRequestMessage()
{
RequestUri = new Uri(this.BaseUrl + "api/Account/RegisterExternal"),
Method = HttpMethod.Post,
};
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", AccessToken);
var content = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string> ("Email", email)
});
request.Content = content;
var authenticateResponse = await Client.SendAsync(request);
if (!authenticateResponse.IsSuccessStatusCode)
{
IsUserRegistered = false;
}
}
return IsUserRegistered;
}
EvZ Ans 后更新
调用扩展方法:
string result = await Task.Run(() => new Service(Settings.BaseUrl, Settings.AccessToken).Register(Model)).ExecuteAsyncOperation();
扩展方法:
public static class TaskExtensions
{
public static async Task<T> ExecuteAsyncOperation<T>(this Task<T> operation)
{
try
{
return await operation;
}
catch
{
return default(T);
}
}
}
扩展您的服务以获得以下方法(根据您的需要):
async Task<T> Post<T>(string url, object body)
async Task<T> Get<T>(string url)
这些方法中的每一个都应该得到一个 HttpResponseMessage
,您应该检查它是成功还是失败。
此外,您可以引入一个 MyApi
class,它将以下面的方式使用您的 Service
class 中的方法:
async AuthenticationResult Authenticate() =>
await service.Post("http://myapi.com/token", new AuthenticationRequest { Username = "x", Password = "xxx"});
P.S.: 请注意 Service
是一个非常糟糕的命名。完全不清楚 Service
class 负责什么。
P.S.S.: 或者,您可以为 Task
创建一个扩展方法来包装所有 api 请求并进行一次 try / catch。
简单示例:
public static class TaskExtensions
{
public static async Task<T> ExecuteAsyncOperation<T>(this Task<T> operation)
{
try
{
return await operation;
}
catch{ }
}
}
var token = await apiService.Authenticate(string username, string password).ExecuteAsyncOperation();