/// <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;
        }
        /// <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;
        }
Example #3
0
        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);
        }