Example #1
0
        private Encoding MatchAcceptCharacterEncoding(string acceptCharsetHeader)
        {
            var acceptCharsetHeaders = HeaderParsingHelpers
                                       .GetAcceptCharsetHeaders(acceptCharsetHeader);

            if (acceptCharsetHeaders != null && acceptCharsetHeaders.Count > 0)
            {
                var sortedAcceptCharsetHeaders = acceptCharsetHeaders
                                                 .Where(acceptCharset =>
                                                        acceptCharset.Quality != HttpHeaderUtilitites.NoMatch)
                                                 .OrderByDescending(
                    m => m, StringWithQualityHeaderValueComparer.QualityComparer);

                foreach (var acceptCharset in sortedAcceptCharsetHeaders)
                {
                    var charset = acceptCharset.Value;
                    if (!string.IsNullOrWhiteSpace(charset))
                    {
                        var encoding = SupportedEncodings.FirstOrDefault(
                            supportedEncoding =>
                            charset.Equals(supportedEncoding.WebName,
                                           StringComparison.OrdinalIgnoreCase) ||
                            charset.Equals("*", StringComparison.OrdinalIgnoreCase));
                        if (encoding != null)
                        {
                            return(encoding);
                        }
                    }
                }
            }

            return(null);
        }
Example #2
0
        public virtual IOutputFormatter SelectFormatter(OutputFormatterContext formatterContext,
                                                        IEnumerable <IOutputFormatter> formatters)
        {
            var incomingAcceptHeader = HeaderParsingHelpers.GetAcceptHeaders(
                formatterContext.ActionContext.HttpContext.Request.Accept);
            var sortedAcceptHeaders = SortMediaTypeWithQualityHeaderValues(incomingAcceptHeader)
                                      .Where(header => header.Quality != HttpHeaderUtilitites.NoMatch)
                                      .ToArray();

            IOutputFormatter selectedFormatter = null;

            if (ContentTypes == null || ContentTypes.Count == 0)
            {
                // Select based on sorted accept headers.
                selectedFormatter = SelectFormatterUsingSortedAcceptHeaders(
                    formatterContext,
                    formatters,
                    sortedAcceptHeaders);

                if (selectedFormatter == null)
                {
                    var requestContentType = formatterContext.ActionContext.HttpContext.Request.ContentType;

                    // No formatter found based on accept headers, fall back on request contentType.
                    MediaTypeHeaderValue incomingContentType = null;
                    MediaTypeHeaderValue.TryParse(requestContentType, out incomingContentType);

                    // In case the incomingContentType is null (as can be the case with get requests),
                    // we need to pick the first formatter which
                    // can support writing this type.
                    var contentTypes = new[] { incomingContentType };
                    selectedFormatter = SelectFormatterUsingAnyAcceptableContentType(
                        formatterContext,
                        formatters,
                        contentTypes);

                    // This would be the case when no formatter could write the type base on the
                    // accept headers and the request content type. Fallback on type based match.
                    if (selectedFormatter == null)
                    {
                        foreach (var formatter in formatters)
                        {
                            var supportedContentTypes = formatter.GetSupportedContentTypes(
                                formatterContext.DeclaredType,
                                formatterContext.Object?.GetType(),
                                contentType: null);

                            if (formatter.CanWriteResult(formatterContext, supportedContentTypes?.FirstOrDefault()))
                            {
                                return(formatter);
                            }
                        }
                    }
                }
            }
            else if (ContentTypes.Count == 1)
            {
                // There is only one value that can be supported.
                selectedFormatter = SelectFormatterUsingAnyAcceptableContentType(
                    formatterContext,
                    formatters,
                    ContentTypes);
            }
            else
            {
                // Filter and remove accept headers which cannot support any of the user specified content types.
                var filteredAndSortedAcceptHeaders = sortedAcceptHeaders
                                                     .Where(acceptHeader =>
                                                            ContentTypes
                                                            .Any(contentType =>
                                                                 contentType.IsSubsetOf(acceptHeader)))
                                                     .ToArray();

                if (filteredAndSortedAcceptHeaders.Length > 0)
                {
                    selectedFormatter = SelectFormatterUsingSortedAcceptHeaders(
                        formatterContext,
                        formatters,
                        filteredAndSortedAcceptHeaders);
                }

                if (selectedFormatter == null)
                {
                    // Either there were no acceptHeaders that were present OR
                    // There were no accept headers which matched OR
                    // There were acceptHeaders which matched but there was no formatter
                    // which supported any of them.
                    // In any of these cases, if the user has specified content types,
                    // do a last effort to find a formatter which can write any of the user specified content type.
                    selectedFormatter = SelectFormatterUsingAnyAcceptableContentType(
                        formatterContext,
                        formatters,
                        ContentTypes);
                }
            }

            return(selectedFormatter);
        }