public void Ctor_ClonesMediaType() { // Arrange MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); MediaTypeHeaderValue mediaType = MediaTypeHeaderValue.Parse("text/test"); // Act MediaTypeFormatterMatch match = new MediaTypeFormatterMatch(formatter, mediaType, null, MediaTypeFormatterMatchRanking.MatchOnCanWriteType); // Assert Assert.Equal(mediaType, match.MediaType); Assert.NotSame(mediaType, match.MediaType); }
public void Ctor_InitializesDefaultValues() { // Arrange MockMediaTypeFormatter formatter = new MockMediaTypeFormatter(); // Act MediaTypeFormatterMatch match = new MediaTypeFormatterMatch(formatter, null, null, MediaTypeFormatterMatchRanking.MatchOnCanWriteType); // Assert Assert.Same(formatter, match.Formatter); Assert.Equal(MediaTypeConstants.ApplicationOctetStreamMediaType, match.MediaType); Assert.Equal(FormattingUtilities.Match, match.Quality); Assert.Equal(MediaTypeFormatterMatchRanking.MatchOnCanWriteType, match.Ranking); }
public void SelectResponseMediaTypeFormatter_SelectsMediaType(ICollection <MediaTypeFormatterMatch> matches, MediaTypeFormatterMatch expectedWinner) { // Arrange MockContentNegotiator negotiator = new MockContentNegotiator(); // Act MediaTypeFormatterMatch actualWinner = negotiator.SelectResponseMediaTypeFormatter(matches); // Assert Assert.Same(expectedWinner, actualWinner); }
/// <summary> /// Evaluates whether a match is better than the current match and if so returns the replacement; otherwise returns the /// current match. /// </summary> protected virtual MediaTypeFormatterMatch UpdateBestMatch(MediaTypeFormatterMatch current, MediaTypeFormatterMatch potentialReplacement) { if (potentialReplacement == null) { return current; } if (current != null) { return (potentialReplacement.Quality > current.Quality) ? potentialReplacement : current; } return potentialReplacement; }
/// <summary> /// Select the best match among the candidate matches found. /// </summary> /// <param name="matches">The collection of matches.</param> /// <returns>The <see cref="MediaTypeFormatterMatch"/> determined to be the best match.</returns> protected virtual MediaTypeFormatterMatch SelectResponseMediaTypeFormatter( ICollection <MediaTypeFormatterMatch> matches) { if (matches == null) { throw new ArgumentNullException(nameof(matches)); } // Performance-sensitive var matchList = matches.AsList(); MediaTypeFormatterMatch bestMatchOnType = null; MediaTypeFormatterMatch bestMatchOnAcceptHeaderLiteral = null; MediaTypeFormatterMatch bestMatchOnAcceptHeaderSubtypeMediaRange = null; MediaTypeFormatterMatch bestMatchOnAcceptHeaderAllMediaRange = null; MediaTypeFormatterMatch bestMatchOnMediaTypeMapping = null; MediaTypeFormatterMatch bestMatchOnRequestMediaType = null; // Go through each formatter to find the best match in each category. for (var i = 0; i < matchList.Count; i++) { var match = matchList[i]; switch (match.Ranking) { case MediaTypeFormatterMatchRanking.MatchOnCanWriteType: // First match by type trumps all other type matches if (bestMatchOnType == null) { bestMatchOnType = match; } break; case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderLiteral: // Matches on accept headers must choose the highest quality match. // A match of 0.0 means we won't use it at all. bestMatchOnAcceptHeaderLiteral = UpdateBestMatch(bestMatchOnAcceptHeaderLiteral, match); break; case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderSubtypeMediaRange: // Matches on accept headers must choose the highest quality match. // A match of 0.0 means we won't use it at all. bestMatchOnAcceptHeaderSubtypeMediaRange = UpdateBestMatch(bestMatchOnAcceptHeaderSubtypeMediaRange, match); break; case MediaTypeFormatterMatchRanking.MatchOnRequestAcceptHeaderAllMediaRange: // Matches on accept headers must choose the highest quality match. // A match of 0.0 means we won't use it at all. bestMatchOnAcceptHeaderAllMediaRange = UpdateBestMatch(bestMatchOnAcceptHeaderAllMediaRange, match); break; case MediaTypeFormatterMatchRanking.MatchOnRequestMediaType: // First match on request content type trumps other request content matches if (bestMatchOnRequestMediaType == null) { bestMatchOnRequestMediaType = 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 (bestMatchOnMediaTypeMapping != null) { var mappingOverride = bestMatchOnMediaTypeMapping; mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderLiteral); mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderSubtypeMediaRange); mappingOverride = UpdateBestMatch(mappingOverride, bestMatchOnAcceptHeaderAllMediaRange); if (mappingOverride != bestMatchOnMediaTypeMapping) { bestMatchOnMediaTypeMapping = 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 MediaTypeFormatterMatch bestMatch = null; if (bestMatchOnMediaTypeMapping != null) { bestMatch = bestMatchOnMediaTypeMapping; } else if (bestMatchOnAcceptHeaderLiteral != null || bestMatchOnAcceptHeaderSubtypeMediaRange != null || bestMatchOnAcceptHeaderAllMediaRange != null) { bestMatch = UpdateBestMatch(bestMatch, bestMatchOnAcceptHeaderLiteral); bestMatch = UpdateBestMatch(bestMatch, bestMatchOnAcceptHeaderSubtypeMediaRange); bestMatch = UpdateBestMatch(bestMatch, bestMatchOnAcceptHeaderAllMediaRange); } else if (bestMatchOnRequestMediaType != null) { bestMatch = bestMatchOnRequestMediaType; } else if (bestMatchOnType != null) { bestMatch = bestMatchOnType; } return(bestMatch); }
public void UpdateBestMatch_SelectsCorrectly(MediaTypeFormatterMatch current, MediaTypeFormatterMatch replacement, bool currentWins) { // Arrange MockContentNegotiator negotiator = new MockContentNegotiator(); // Act MediaTypeFormatterMatch actualResult = negotiator.UpdateBestMatch(current, replacement); // Assert if (currentWins) { Assert.Same(current, actualResult); } else { Assert.Same(replacement, actualResult); } }
/// <summary> /// Evaluates whether a match is better than the current match and if so returns the replacement; otherwise returns the /// current match. /// </summary> protected virtual MediaTypeFormatterMatch UpdateBestMatch(MediaTypeFormatterMatch current, MediaTypeFormatterMatch potentialReplacement) { if (potentialReplacement == null) { return(current); } if (current != null) { return((potentialReplacement.Quality > current.Quality) ? potentialReplacement : current); } return(potentialReplacement); }
/// <summary> /// Determine how well each formatter matches by associating a <see cref="MediaTypeFormatterMatchRanking"/> value /// with the formatter. Then associate the quality of the match based on q-factors and other parameters. The result of this /// method is a collection of the matches found categorized and assigned a quality value. /// </summary> /// <param name="type">The type to be serialized.</param> /// <param name="request">The request.</param> /// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param> /// <returns>A collection containing all the matches.</returns> protected virtual Collection <MediaTypeFormatterMatch> ComputeFormatterMatches(Type type, HttpRequestMessage request, IEnumerable <MediaTypeFormatter> formatters) { // Performance-sensitive if (type == null) { throw Error.ArgumentNull("type"); } if (request == null) { throw Error.ArgumentNull("request"); } if (formatters == null) { throw Error.ArgumentNull("formatters"); } IEnumerable <MediaTypeWithQualityHeaderValue> sortedAcceptValues = null; // Go through each formatter to find how well it matches. ListWrapperCollection <MediaTypeFormatterMatch> matches = new ListWrapperCollection <MediaTypeFormatterMatch>(); MediaTypeFormatter[] writingFormatters = GetWritingFormatters(formatters); for (int i = 0; i < writingFormatters.Length; i++) { MediaTypeFormatter formatter = writingFormatters[i]; MediaTypeFormatterMatch match = null; // Check first that formatter can write the actual type if (!formatter.CanWriteType(type)) { // Formatter can't even write the type so no match at all continue; } // Match against media type mapping. if ((match = MatchMediaTypeMapping(request, formatter)) != null) { matches.Add(match); continue; } // Match against the accept header values. if (sortedAcceptValues == null) { // Sort the Accept header values in descending order based on q-factor sortedAcceptValues = SortMediaTypeWithQualityHeaderValuesByQFactor(request.Headers.Accept); } if ((match = MatchAcceptHeader(sortedAcceptValues, formatter)) != null) { matches.Add(match); continue; } // Match against request's media type if any if ((match = MatchRequestMediaType(request, formatter)) != null) { matches.Add(match); continue; } // Check whether we should match on type or stop the matching process. // The latter is used to generate 406 (Not Acceptable) status codes. bool shouldMatchOnType = ShouldMatchOnType(sortedAcceptValues); // Match against the type of object we are writing out if (shouldMatchOnType && (match = MatchType(type, formatter)) != null) { matches.Add(match); continue; } } return(matches); }
public void SelectResponseMediaTypeFormatter_SelectsMediaType(ICollection<MediaTypeFormatterMatch> matches, MediaTypeFormatterMatch expectedWinner) { // Arrange MockContentNegotiator negotiator = new MockContentNegotiator(); // Act MediaTypeFormatterMatch actualWinner = negotiator.SelectResponseMediaTypeFormatter(matches); // Assert Assert.Same(expectedWinner, actualWinner); }
/// <summary> /// Determine how well each formatter matches by associating a <see cref="MediaTypeFormatterMatchRanking"/> value /// with the formatter. Then associate the quality of the match based on q-factors and other parameters. The result of this /// method is a collection of the matches found categorized and assigned a quality value. /// </summary> /// <param name="type">The type to be serialized.</param> /// <param name="request">The request.</param> /// <param name="formatters">The set of <see cref="MediaTypeFormatter"/> objects from which to choose.</param> /// <returns>A collection containing all the matches.</returns> protected virtual Collection <MediaTypeFormatterMatch> ComputeFormatterMatches(Type type, HttpRequestMessage request, IEnumerable <MediaTypeFormatter> formatters) { if (type == null) { throw Error.ArgumentNull("type"); } if (request == null) { throw Error.ArgumentNull("request"); } if (formatters == null) { throw Error.ArgumentNull("formatters"); } IEnumerable <MediaTypeWithQualityHeaderValue> sortedAcceptValues = null; // Go through each formatter to find how well it matches. Collection <MediaTypeFormatterMatch> matches = new Collection <MediaTypeFormatterMatch>(); foreach (MediaTypeFormatter formatter in formatters) { MediaTypeFormatterMatch match = null; // Check first that formatter can write the actual type if (!formatter.CanWriteType(type)) { // Formatter can't even write the type so no match at all continue; } // Match against media type mapping. if ((match = MatchMediaTypeMapping(request, formatter)) != null) { matches.Add(match); continue; } // Match against the accept header values. if (sortedAcceptValues == null) { // Sort the Accept header values in descending order based on q-factor sortedAcceptValues = SortMediaTypeWithQualityHeaderValuesByQFactor(request.Headers.Accept); } if ((match = MatchAcceptHeader(sortedAcceptValues, formatter)) != null) { matches.Add(match); continue; } // Match against request's media type if any if ((match = MatchRequestMediaType(request, formatter)) != null) { matches.Add(match); continue; } // Match against the type of object we are writing out if ((match = MatchType(type, formatter)) != null) { matches.Add(match); continue; } } return(matches); }