/// <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; }
/// <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); }