当前位置 > 首页 > Asp.net

Asp.net web Api源码分析-HttpResponseMessage

2012-12-6 20:11:00来源:Asp.net

紧接着上文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的创建
曾提到Formatters主要有JsonMediaTypeFormatter,XmlMediaTypeFormatter, FormUrlEncodedMediaTypeFormatter,JQueryMvcFormUrlEncodedFormatter这4个。接着我们知道要干什么了,需要把我们的value转换为需要的格式,这里创建一个 ContentNegotiationResult result = contentNegotiator.Negotiate(typeof(T), request, formatters);实例,其中Negotiate的主要实现如下:

public virtual ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
        {
             ....。。。。。。
            // Go through each formatter to compute how well it matches.
            Collection<MediaTypeFormatterMatch> matches = ComputeFormatterMatches(type, request, formatters);

            // Select best formatter match among the matches
            MediaTypeFormatterMatch bestFormatterMatch = SelectResponseMediaTypeFormatter(matches);

            // We found a best formatter
            if (bestFormatterMatch != null)
            {
                // Find the best character encoding for the selected formatter
                Encoding bestEncodingMatch = SelectResponseCharacterEncoding(request, bestFormatterMatch.Formatter);
                if (bestEncodingMatch != null)
                {
                    bestFormatterMatch.MediaType.CharSet = bestEncodingMatch.WebName;
                }

                MediaTypeHeaderValue bestMediaType = bestFormatterMatch.MediaType;
                MediaTypeFormatter bestFormatter = bestFormatterMatch.Formatter.GetPerRequestFormatterInstance(type, request, bestMediaType);
                return new ContentNegotiationResult(bestFormatter, bestMediaType);
            }

            return null;
        }
这里的Negotiate方法实现比较复杂,首先找到当前请求支持的一个MediaTypeFormatterMatch集合,然后再从这个集合中找到找最合适一个