【发布时间】:2013-02-25 04:38:37
【问题描述】:
我正在编写一个使用 ASP.NET Web API 代理一些 HTTP 请求的应用程序,并且我正在努力确定间歇性错误的来源。 这似乎是一种竞争条件......但我并不完全确定。
在我详细介绍之前,这里是应用程序的一般通信流程:
- 客户端向代理 1 发出 HTTP 请求。
- 代理 1 将 HTTP 请求的内容中继到代理 2
- 代理 2 将 HTTP 请求的内容中继到目标 Web 应用程序
- 目标 Web 应用响应 HTTP 请求并将响应流式传输(分块传输)到代理 2
- Proxy 2 将响应返回给 Proxy 1,后者又响应原始调用 Client。
代理应用程序是使用 .NET 4.5 在 ASP.NET Web API RTM 中编写的。 执行中继的代码如下所示:
//Controller entry point.
public HttpResponseMessage Post()
{
using (var client = new HttpClient())
{
var request = BuildRelayHttpRequest(this.Request);
//HttpCompletionOption.ResponseHeadersRead - so that I can start streaming the response as soon
//As it begins to filter in.
var relayResult = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
var returnMessage = BuildResponse(relayResult);
return returnMessage;
}
}
private static HttpRequestMessage BuildRelayHttpRequest(HttpRequestMessage incomingRequest)
{
var requestUri = BuildRequestUri();
var relayRequest = new HttpRequestMessage(incomingRequest.Method, requestUri);
if (incomingRequest.Method != HttpMethod.Get && incomingRequest.Content != null)
{
relayRequest.Content = incomingRequest.Content;
}
//Copies all safe HTTP headers (mainly content) to the relay request
CopyHeaders(relayRequest, incomingRequest);
return relayRequest;
}
private static HttpRequestMessage BuildResponse(HttpResponseMessage responseMessage)
{
var returnMessage = Request.CreateResponse(responseMessage.StatusCode);
returnMessage.ReasonPhrase = responseMessage.ReasonPhrase;
returnMessage.Content = CopyContentStream(responseMessage);
//Copies all safe HTTP headers (mainly content) to the response
CopyHeaders(returnMessage, responseMessage);
}
private static PushStreamContent CopyContentStream(HttpResponseMessage sourceContent)
{
var content = new PushStreamContent(async (stream, context, transport) =>
await sourceContent.Content.ReadAsStreamAsync()
.ContinueWith(t1 => t1.Result.CopyToAsync(stream)
.ContinueWith(t2 => stream.Dispose())));
return content;
}
间歇性出现的错误是:
异步模块或处理程序已完成,而异步操作仍处于挂起状态。
此错误通常发生在对代理应用程序的前几次请求中,之后该错误不再出现。
Visual Studio 永远不会在抛出异常时捕获异常。 但是可以在 Global.asax Application_Error 事件中捕获错误。 不幸的是,异常没有堆栈跟踪。
代理应用程序托管在 Azure Web 角色中。
任何帮助确定罪魁祸首将不胜感激。
【问题讨论】:
-
CopyHeaders 是我编写的一种方法,用于中继我认为适合为我的应用程序复制的 HTTP 标头。它没有包括在这里,因为它与我试图解决的问题无关。我最终得到的解决方案类似于下面接受的答案,应该足以让您编写类似的解决方案。
标签: c# asp.net asp.net-web-api dotnet-httpclient