我对一个返回任务的webapi客户端进行了多次调用 像这样的东西
public async Task<TResp> GetMyThingAsync(TReq req)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(BaseURI);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml"));
await HttpRuntime.Cache.GetToken().ContinueWith((t) =>
{
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("XXX", t.Result);
});
var httpResponseMessage = await client.PostAsXmlAsync<TReq>("This/That/", req);
httpResponseMessage.EnsureSuccessStatusCode();
var resp = await httpResponseMessage.Content.ReadAsAsync<TResp>();
return resp;
}
}
对api的调用当然可以返回500或其他一些问题。如果类似的事情发生,EnsureSuccessStatusCode()
显然会抛出,但是对于响应中的任何信息做任何事都为时已晚。
有一个很好的方法来处理这个?
我知道你可以在客户端添加一个messageHandler,比如
HttpClient client = HttpClientFactory(new ErrorMessageHandler())
..
var customHandler = new ErrorMessageHandler()
{ InnerHandler = new HttpClientHandler()};
HttpClient client = new HttpClient(customHandler);
这是要走的路吗? ErroMessageHandler会是什么样子,并且会向调用控制器返回一些有用的东西......?
非常感谢
NAT
答案 0 :(得分:1)
创建自定义处理程序可以成为记录异常或验证响应的优雅解决方案。如果遇到异常,我不确定被叫控制器是否正在等待来自客户端的有意义的响应。我认为真正重要的部分是确保您(客户端)优雅地处理Web apis错误。
这可以通过以下两种方式完成:
您可以在调用方法中本地处理异常。您可以使用HttpResponseMessage.IsSuccessStatusCode
属性指示是否返回错误响应而不是调用引发异常的httpResponseMessage.EnsureSuccessStatusCode()
,并返回自定义ErrorResponse(或执行您决定的任何操作):
var client = new HttpClient() // No need to dispose HttpClient
client.BaseAddress = new Uri(BaseURI);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xml"));
var token = await HttpRuntime.Cache.GetToken();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("XXX", token);
var httpResponseMessage = await client.PostAsXmlAsync<TReq>("This/That/", req);
if (!httpResponseMessage.IsSuccessStatusCode)
{
return Task.FromResult(new ErrorResponse()) // Create some kind of error response to indicate failure
}
var resp = await httpResponseMessage.Content.ReadAsAsync<TResp>();
return resp;
创建一个ErrorLoggingHandler,它可以记录从web api收到的异常(或做其他事情):
public class ErrorLoggingHandler : DelegatingHandler
{
private readonly StreamWriter _writer; // As a sample, log to a StreamWriter
public ErrorLoggingHandler(Stream stream)
{
_writer = new StreamWriter(stream);
}
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
if (!response.IsSuccessStatusCode)
{
// This would probably be replaced with real error
// handling logic (return some kind of special response etc..)
_writer.WriteLine("{0}\t{1}\t{2}", request.RequestUri,
(int) response.StatusCode, response.Headers.Date);
}
return response;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_writer.Dispose();
}
base.Dispose(disposing);
}
}
然后,您可以使用HttpClient
创建HttpClientFactory
:
var httpclient = HttpClientFactory.Create(new ErrorLoggingHandler(new FileStream(@"Location", FileMode.OpenOrCreate)));