/// <summary> /// Initializes a new instance of the <see cref="ResponseMediaTypeMatch"/> class. /// </summary> /// <param name="mediaTypeMatch">The <see cref="MediaTypeMatch"/> containing the media type and its quality factor.</param> /// <param name="result">The kind of match.</param> public ResponseMediaTypeMatch(MediaTypeMatch mediaTypeMatch, ResponseFormatterSelectionResult result) { Contract.Assert(mediaTypeMatch != null, "mediaTypeMatch cannot be null."); Contract.Assert(Enum.IsDefined(typeof(ResponseFormatterSelectionResult), result), "result must be valid ResponseFormatterSelectionResult."); ResponseFormatterSelectionResult = result; MediaTypeMatch = mediaTypeMatch; }
private static MediaTypeFormatter RunNegotiation(Type type, HttpRequestMessage request, IEnumerable <MediaTypeFormatter> formatters, out MediaTypeHeaderValue mediaType) { // Asking to serialize a response. This is the nominal code path. // We ask all formatters for their best kind of match, and then we // choose the best among those. MediaTypeFormatter formatterMatchOnType = null; ResponseMediaTypeMatch mediaTypeMatchOnType = null; MediaTypeFormatter formatterMatchOnAcceptHeader = null; ResponseMediaTypeMatch mediaTypeMatchOnAcceptHeader = null; MediaTypeFormatter formatterMatchWithMapping = null; ResponseMediaTypeMatch mediaTypeMatchWithMapping = null; MediaTypeFormatter formatterMatchOnRequestContentType = null; ResponseMediaTypeMatch mediaTypeMatchOnRequestContentType = null; foreach (MediaTypeFormatter formatter in formatters) { ResponseMediaTypeMatch match = formatter.SelectResponseMediaType(type, request); if (match == null) { // Null signifies no match continue; } ResponseFormatterSelectionResult matchResult = match.ResponseFormatterSelectionResult; switch (matchResult) { case ResponseFormatterSelectionResult.MatchOnCanWriteType: // First match by type trumps all other type matches if (formatterMatchOnType == null) { formatterMatchOnType = formatter; mediaTypeMatchOnType = match; } break; case ResponseFormatterSelectionResult.MatchOnResponseContentType: // Match on response content trumps all other choices mediaType = match.MediaTypeMatch.MediaType; return(formatter); case ResponseFormatterSelectionResult.MatchOnRequestAcceptHeader: // Matches on accept headers must choose the highest quality match double thisQuality = match.MediaTypeMatch.Quality; if (formatterMatchOnAcceptHeader != null) { double bestQualitySeen = mediaTypeMatchOnAcceptHeader.MediaTypeMatch.Quality; if (thisQuality <= bestQualitySeen) { continue; } } formatterMatchOnAcceptHeader = formatter; mediaTypeMatchOnAcceptHeader = match; break; case ResponseFormatterSelectionResult.MatchOnRequestWithMediaTypeMapping: // Matches on accept headers using mappings must choose the highest quality match double thisMappingQuality = match.MediaTypeMatch.Quality; if (mediaTypeMatchWithMapping != null) { double bestMappingQualitySeen = mediaTypeMatchWithMapping.MediaTypeMatch.Quality; if (thisMappingQuality <= bestMappingQualitySeen) { continue; } } formatterMatchWithMapping = formatter; mediaTypeMatchWithMapping = match; break; case ResponseFormatterSelectionResult.MatchOnRequestContentType: // First match on request content type trumps other request content matches if (formatterMatchOnRequestContentType == null) { formatterMatchOnRequestContentType = formatter; mediaTypeMatchOnRequestContentType = match; } break; } } // If we received matches based on both supported media types and from media type mappings, // we want to give precedence to the media type mappings, but only if their quality is >= that of the supported media type. // We do this because media type mappings are the user's extensibility point and must take precedence over normal // supported media types in the case of a tie. The 99% case is where both have quality 1.0. if (mediaTypeMatchWithMapping != null && mediaTypeMatchOnAcceptHeader != null) { if (mediaTypeMatchOnAcceptHeader.MediaTypeMatch.Quality > mediaTypeMatchWithMapping.MediaTypeMatch.Quality) { formatterMatchWithMapping = null; } } // now select the formatter and media type // A MediaTypeMapping is highest precedence -- it is an extensibility point // allowing the user to override normal accept header matching if (formatterMatchWithMapping != null) { mediaType = mediaTypeMatchWithMapping.MediaTypeMatch.MediaType; return(formatterMatchWithMapping); } else if (formatterMatchOnAcceptHeader != null) { mediaType = mediaTypeMatchOnAcceptHeader.MediaTypeMatch.MediaType; return(formatterMatchOnAcceptHeader); } else if (formatterMatchOnRequestContentType != null) { mediaType = mediaTypeMatchOnRequestContentType.MediaTypeMatch.MediaType; return(formatterMatchOnRequestContentType); } else if (formatterMatchOnType != null) { mediaType = mediaTypeMatchOnType.MediaTypeMatch.MediaType; return(formatterMatchOnType); } mediaType = null; return(null); }