紧接着前文Asp.net web Api源码分析-如何获取IHttpHandler 我们已经得到了HttpControllerHandler实例,它是一个IHttpAsyncHandler类型,我们来看看它的BeginProcessRequest方法是如何实现:
protected virtual IAsyncResult BeginProcessRequest(HttpContextBase httpContextBase, AsyncCallback callback, object state)
{
HttpRequestMessage request = httpContextBase.GetHttpRequestMessage() ?? ConvertRequest(httpContextBase);
request.Properties[HttpPropertyKeys.HttpRouteDataKey] = _routeData;
Task responseBodyTask = _server.Value.SendAsync(request, CancellationToken.None)
.Then(response => ConvertResponse(httpContextBase, response, request));
TaskWrapperAsyncResult result = new TaskWrapperAsyncResult(responseBodyTask, state);
if (callback != null)
{
if (result.IsCompleted)
{
result.CompletedSynchronously = true;
callback(result);
}
else
{
result.CompletedSynchronously = false;
responseBodyTask.ContinueWith(_ =>
{
callback(result);
});
}
}
return result;
}
我想这个方法的大致逻辑大家一看也就明白了,这里我们只关心 HttpRequestMessage request = httpContextBase.GetHttpRequestMessage() ?? ConvertRequest(httpContextBase);这句,创建HttpRequestMessage实例,有关HttpRequestMessage的一些介绍大家可以参考
MVC4 WebAPI(二)——Web API工作方式
其中GetHttpRequestMessage方法的实现非常简单:
internal static readonly string HttpRequestMessageKey = "MS_HttpRequestMessage";
public static HttpRequestMessage GetHttpRequestMessage(this HttpContextBase context)
{
return context.Items[HttpRequestMessageKey] as HttpRequestMessage;
}
public static void SetHttpRequestMessage(this HttpContextBase context, HttpRequestMessage request)
{
context.Items.Add(HttpRequestMessageKey, request);
}
所以这里的GetHttpRequestMessage并没有真正创建HttpRequestMessage,ConvertRequest方法才是真正创建HttpRequestMessage的地方。
internal static HttpRequestMessage ConvertRequest(HttpContextBase httpContextBase)
{
Contract.Assert(httpContextBase != null);
HttpRequestBase requestBase = httpContextBase.Request;
HttpMethod method = HttpMethodHelper.GetHttpMethod(requestBase.HttpMethod);
Uri uri = requestBase.Url;
HttpRequestMessage request = new HttpRequestMessage(method, uri);
IHostBufferPolicySelector policySelector = _bufferPolicySelector.Value;
bool isInputBuffered = policySelector == null ? true : policySelector.UseBufferedInputStream(httpContextBase);
Stream inputStream = isInputBuffered
? requestBase.InputStream
: httpContextBase.ApplicationInstance.Request.GetBufferlessInputStream();
request.Content = new StreamContent(inputStream);
foreach (string headerName in requestBase.Headers)
{
string[] values = requestBase.Headers.GetValues(headerName);
AddHeaderToHttpRequestMessage(request, headerName, values);
}
request.Properties.Add(HttpContextBaseKey, httpContextBase);
request.Properties.Add(HttpPropertyKeys.RetrieveClientCertificateDelegateKey, _retrieveClientCertificate);
request.Properties.Add(HttpPropertyKeys.