Exemple #1
0
        /// <summary>
        /// Gets the default media type for a given payload kind in a given format.
        /// </summary>
        /// <param name="payloadKind">The kind of payload to write.</param>
        /// <param name="specifiedFormat">The format in which to write the payload (can be ODataFormat.Default).</param>
        /// <param name="actualFormat">The default format for the specified payload kind (is never ODataFormat.Default)</param>
        /// <returns>The default media type for the given payload kind and format.</returns>
        private static MediaType GetDefaultMediaType(ODataPayloadKind payloadKind, ODataFormat specifiedFormat, out ODataFormat actualFormat)
        {
            // get the supported and default media types for the specified payload kind
            MediaTypeWithFormat[] supportedMediaTypes = mediaTypesForPayloadKind[(int)payloadKind];

            for (int i = 0; i < supportedMediaTypes.Length; ++i)
            {
                // NOTE: the supportedMediaTypes are sorted (desc) by format and media type; so the
                //       default format and media type is the first entry in the array
                MediaTypeWithFormat supportedMediaType = supportedMediaTypes[i];
                if (specifiedFormat == ODataFormat.Default || supportedMediaType.Format == specifiedFormat)
                {
                    actualFormat = supportedMediaType.Format;
                    return(supportedMediaType.MediaType);
                }
            }

            throw new ODataException(Strings.ODataUtils_DidNotFindDefaultMediaType(specifiedFormat.ToString()));
        }
        /// <summary>
        /// Matches the supported media types against the list of acceptable media types specified in the Accept header of the request. Matching follows the
        /// rules for media type matching as described in RFC 2616.
        /// </summary>
        /// <param name="acceptableTypes">The set of acceptable media types specified in the Accept header of the request.</param>
        /// <param name="supportedMediaTypes">The set of supported media types (sorted in descending precedence order).</param>
        /// <param name="format">The <see cref="ODataFormat"/> for the selected media type.</param>
        /// <returns>The media type that best matches the acceptable media types.</returns>
        private static MediaType MatchMediaTypes(IList<MediaType> acceptableTypes, MediaTypeWithFormat[] supportedMediaTypes, out ODataFormat format)
        {
            Debug.Assert(supportedMediaTypes != null, "supportedMediaTypes != null");

            MediaTypeWithFormat selectedContentType = null;
            int selectedMatchingTypeNameParts = -1;
            int selectedMatchingParameters = -2;        // -2 is an invalid value; GetMatchingParameters returns values >= -1
            int selectedQualityValue = 0;
            int selectedPreferenceIndex = Int32.MaxValue;
            bool selectedAcceptable = false;

            if (acceptableTypes != null)
            {
                foreach (MediaType acceptableType in acceptableTypes)
                {
                    for (int i = 0; i < supportedMediaTypes.Length; i++)
                    {
                        MediaTypeWithFormat supportedType = supportedMediaTypes[i];

                        // match the type name parts and parameters of the media type
                        int matchingParameters, matchingQualityValue, acceptableTypeParameterCount;
                        int matchingTypeNameParts = acceptableType.GetMatchingParts(supportedType.MediaType, out matchingParameters, out matchingQualityValue, out acceptableTypeParameterCount);

                        if (!IsValidCandidate(matchingTypeNameParts, matchingParameters, acceptableTypeParameterCount))
                        {
                            continue;
                        }

                        // only continue processing the type if it is acceptable or we don't have
                        // an acceptable type yet.
                        bool matchingAcceptable = matchingQualityValue != 0;
                        if (!matchingAcceptable && selectedAcceptable)
                        {
                            continue;
                        }

                        PrecedenceLevel precedence = ComputePrecedence(selectedAcceptable, matchingTypeNameParts, selectedMatchingTypeNameParts, matchingParameters, selectedMatchingParameters);
                        switch (precedence)
                        {
                            case PrecedenceLevel.Higher:
                                {
                                    // A more specific type wins.
                                    selectedContentType = supportedType;
                                    selectedMatchingTypeNameParts = matchingTypeNameParts;
                                    selectedMatchingParameters = matchingParameters;
                                    selectedQualityValue = matchingQualityValue;
                                    selectedPreferenceIndex = i;
                                    selectedAcceptable = matchingAcceptable;
                                }

                                break;
                            case PrecedenceLevel.Same:
                                {
                                    // A type with a higher q-value wins.
                                    if (matchingQualityValue > selectedQualityValue)
                                    {
                                        selectedContentType = supportedType;
                                        selectedQualityValue = matchingQualityValue;
                                        selectedPreferenceIndex = i;
                                        selectedAcceptable = selectedQualityValue != 0;
                                    }
                                    else if (matchingQualityValue == selectedQualityValue)
                                    {
                                        // A type that is earlier in the supportedMediaTypes array wins.
                                        if (i < selectedPreferenceIndex)
                                        {
                                            selectedContentType = supportedType;
                                            selectedPreferenceIndex = i;
                                        }
                                    }
                                }

                                break;
                            case PrecedenceLevel.Lower:
                                continue;
                            default:
                                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataUtils_MatchMediaTypes_UnreachableCodePath));
                        }
                    }
                }
            }

            if (acceptableTypes == null || acceptableTypes.Count == 0)
            {
                // if not acceptable types are specified it means that all types are supported;
                // take the first supported type (as they are oredered by priority/precedence)
                selectedContentType = supportedMediaTypes[0];
            }
            else if (!selectedAcceptable)
            {
                format = ODataFormat.Default;
                return null;
            }

            format = selectedContentType.Format;
            return selectedContentType.MediaType;
        }
Exemple #3
0
        /// <summary>
        /// Matches the supported media types against the list of acceptable media types specified in the Accept header of the request. Matching follows the
        /// rules for media type matching as described in RFC 2616.
        /// </summary>
        /// <param name="acceptableTypes">The set of acceptable media types specified in the Accept header of the request.</param>
        /// <param name="supportedMediaTypes">The set of supported media types (sorted in descending precedence order).</param>
        /// <param name="format">The <see cref="ODataFormat"/> for the selected media type.</param>
        /// <returns>The media type that best matches the acceptable media types.</returns>
        private static MediaType MatchMediaTypes(IList <MediaType> acceptableTypes, MediaTypeWithFormat[] supportedMediaTypes, out ODataFormat format)
        {
            Debug.Assert(supportedMediaTypes != null, "supportedMediaTypes != null");

            MediaTypeWithFormat selectedContentType = null;
            int  selectedMatchingTypeNameParts      = -1;
            int  selectedMatchingParameters         = -2;// -2 is an invalid value; GetMatchingParameters returns values >= -1
            int  selectedQualityValue    = 0;
            int  selectedPreferenceIndex = Int32.MaxValue;
            bool selectedAcceptable      = false;

            if (acceptableTypes != null)
            {
                foreach (MediaType acceptableType in acceptableTypes)
                {
                    for (int i = 0; i < supportedMediaTypes.Length; i++)
                    {
                        MediaTypeWithFormat supportedType = supportedMediaTypes[i];

                        // match the type name parts and parameters of the media type
                        int matchingParameters, matchingQualityValue, acceptableTypeParameterCount;
                        int matchingTypeNameParts = acceptableType.GetMatchingParts(supportedType.MediaType, out matchingParameters, out matchingQualityValue, out acceptableTypeParameterCount);

                        if (!IsValidCandidate(matchingTypeNameParts, matchingParameters, acceptableTypeParameterCount))
                        {
                            continue;
                        }

                        // only continue processing the type if it is acceptable or we don't have
                        // an acceptable type yet.
                        bool matchingAcceptable = matchingQualityValue != 0;
                        if (!matchingAcceptable && selectedAcceptable)
                        {
                            continue;
                        }

                        PrecedenceLevel precedence = ComputePrecedence(selectedAcceptable, matchingTypeNameParts, selectedMatchingTypeNameParts, matchingParameters, selectedMatchingParameters);
                        switch (precedence)
                        {
                        case PrecedenceLevel.Higher:
                        {
                            // A more specific type wins.
                            selectedContentType           = supportedType;
                            selectedMatchingTypeNameParts = matchingTypeNameParts;
                            selectedMatchingParameters    = matchingParameters;
                            selectedQualityValue          = matchingQualityValue;
                            selectedPreferenceIndex       = i;
                            selectedAcceptable            = matchingAcceptable;
                        }

                        break;

                        case PrecedenceLevel.Same:
                        {
                            // A type with a higher q-value wins.
                            if (matchingQualityValue > selectedQualityValue)
                            {
                                selectedContentType     = supportedType;
                                selectedQualityValue    = matchingQualityValue;
                                selectedPreferenceIndex = i;
                                selectedAcceptable      = selectedQualityValue != 0;
                            }
                            else if (matchingQualityValue == selectedQualityValue)
                            {
                                // A type that is earlier in the supportedMediaTypes array wins.
                                if (i < selectedPreferenceIndex)
                                {
                                    selectedContentType     = supportedType;
                                    selectedPreferenceIndex = i;
                                }
                            }
                        }

                        break;

                        case PrecedenceLevel.Lower:
                            continue;

                        default:
                            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataUtils_MatchMediaTypes_UnreachableCodePath));
                        }
                    }
                }
            }

            if (acceptableTypes == null || acceptableTypes.Count == 0)
            {
                // if not acceptable types are specified it means that all types are supported;
                // take the first supported type (as they are oredered by priority/precedence)
                selectedContentType = supportedMediaTypes[0];
            }
            else if (!selectedAcceptable)
            {
                format = ODataFormat.Default;
                return(null);
            }

            format = selectedContentType.Format;
            return(selectedContentType.MediaType);
        }