在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
紧接着上文Asp.net web Api源码分析-Action的执行 我们的Action已经执行完毕,现在需要把Action的返回结果转化为HttpResponseMessage 实例,我们也知道转化工作主要在HttpRequestMessage的CreateResponse附加方法中, public static HttpResponseMessage CreateResponse<T>(this HttpRequestMessage request, HttpStatusCode statusCode, T value, HttpConfiguration configuration) { if (request == null) { throw Error.ArgumentNull("request"); } configuration = configuration ?? request.GetConfiguration(); if (configuration == null) { throw Error.InvalidOperation(SRResources.HttpRequestMessageExtensions_NoConfiguration); } IContentNegotiator contentNegotiator = configuration.Services.GetContentNegotiator(); if (contentNegotiator == null) { throw Error.InvalidOperation(SRResources.HttpRequestMessageExtensions_NoContentNegotiator, typeof(IContentNegotiator).FullName); } IEnumerable<MediaTypeFormatter> formatters = configuration.Formatters; // Run content negotiation ContentNegotiationResult result = contentNegotiator.Negotiate(typeof(T), request, formatters); if (result == null) { // no result from content negotiation indicates that 406 should be sent. return new HttpResponseMessage { StatusCode = HttpStatusCode.NotAcceptable, RequestMessage = request, }; } else { MediaTypeHeaderValue mediaType = result.MediaType; return new HttpResponseMessage { // At this point mediaType should be a cloned value (the content negotiator is responsible for returning a new copy) Content = new ObjectContent<T>(value, result.Formatter, mediaType), StatusCode = statusCode, RequestMessage = request }; } }
首先这里需要一个IContentNegotiator实例,这里有这么一句代码: IContentNegotiator contentNegotiator = configuration.Services.GetContentNegotiator();在DefaultServices中有 SetSingle<IContentNegotiator>(new DefaultContentNegotiator());这句,我们知道默认的contentNegotiator是DefaultContentNegotiator实例。DefaultContentNegotiator构造函数也比较普通,这里我们还需要一个数据的格式化Formatters,这里有这么一句 IEnumerable<MediaTypeFormatter> formatters = configuration.Formatters;,在Asp.net web Api源码分析-HttpServer的创建
public virtual ContentNegotiationResult Negotiate(Type type,
HttpRequestMessage request, IEnumerable<MediaTypeFormatter>
formatters) 现在我们回到CreateResponse方法中来,最后直接返回一个 HttpResponseMessage实例。 MediaTypeHeaderValue mediaType = result.MediaType;
return new HttpResponseMessage 这里的ObjectContent的创建也比较一般,我们也就忽略它吧。 现在我们回到HttpControllerHandler的BeginProcessRequest方法中来, Task responseBodyTask = _server.Value.SendAsync(request, CancellationToken.None) SendAsync已经执行完毕了,我们再来看看ConvertResponse吧,它主要就是把HttpResponseMessage的信息写到HttpResponseBase信息做。 internal static Task ConvertResponse(HttpContextBase
httpContextBase, HttpResponseMessage response, HttpRequestMessage
request) 这里的CopyResponseStatusAndHeaders方法比较简单我也不多说了,就是把HttpResponseMessage中的StatusAndHeaders信息写到 httpContextBase.Response中去, 我们还是关注一下WriteResponseContentAsync的实现吧: internal static Task WriteResponseContentAsync(HttpContextBase
httpContextBase, HttpResponseMessage response, HttpRequestMessage
request) 前面CopyResponseStatusAndHeaders方法把HttpResponseMessage中的Headers信息写到 httpContextBase.Response中去了,这里继续把response.Content.Headers信息写到 httpContextBase.Response中去。 private static readonly Lazy<IHostBufferPolicySelector>
_bufferPolicySelector = 在GlobalConfiguration中有这么一句 config.Services.Replace(typeof(IHostBufferPolicySelector), new WebHostBufferPolicySelector());所以我们知道_bufferPolicySelector这里其实是一个WebHostBufferPolicySelector实例,这里调用WebHostBufferPolicySelector的UseBufferedOutputStream方法来获取当前输出信息是否采用输出缓存,一般情况下这个个方法返回true,主要实现如下: public virtual bool UseBufferedOutputStream(HttpResponseMessage response) 一般情况下response.Content.Headers.ContentLength为null。所以后面调用的是WriteBufferedResponseContentAsync方法,而该方法的主要实现就一句代码 Task writeResponseContentTask = HttpResponseMessage.Content.CopyToAsync(HttpContextBase.Response.OutputStream);把当前HttpResponseMessage.Content中的数据全部写到HttpContextBase.Response.OutputStream中去。到这里我们的BeginProcessRequest就差不多执行完了,后面就是调用回调函数的事情了。 到本章为止,整个web api的主要流程就说完了,这个系列中有关参数的具体绑定和返回值的格式化我是忽略了的,他们的实现都相对比较复杂,后面再抽时间来看看他们是如何实现 吧,个人对web api也不是很熟悉,发现它和mvc 中的很多代码相似,相比之下mvc的使用比web api要广泛得多,所以这里建议大家多读读mvc的源码,读了之后再来读web api源码相对要轻松很多了。 |
请发表评论