diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/OutputFormatterCanWriteContext.cs b/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/OutputFormatterCanWriteContext.cs
index 4a2f905d38..588e13db40 100644
--- a/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/OutputFormatterCanWriteContext.cs
+++ b/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/OutputFormatterCanWriteContext.cs
@@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using Microsoft.Net.Http.Headers;
+using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNet.Mvc.Formatters
{
@@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
/// and expect to see the same value provided in
///
///
- public virtual MediaTypeHeaderValue ContentType { get; set; }
+ public virtual StringSegment ContentType { get; set; }
///
/// Gets or sets a value indicating that content-negotiation could not find a formatter based on the
diff --git a/src/Microsoft.AspNet.Mvc.ApiExplorer/ApiResponseFormat.cs b/src/Microsoft.AspNet.Mvc.ApiExplorer/ApiResponseFormat.cs
index dad272f440..ff475cb545 100644
--- a/src/Microsoft.AspNet.Mvc.ApiExplorer/ApiResponseFormat.cs
+++ b/src/Microsoft.AspNet.Mvc.ApiExplorer/ApiResponseFormat.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc.Formatters;
-using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.ApiExplorer
{
@@ -19,6 +18,6 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
///
/// The media type of the response.
///
- public MediaTypeHeaderValue MediaType { get; set; }
+ public string MediaType { get; set; }
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs b/src/Microsoft.AspNet.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs
index ccfde0a0dd..c79a935497 100644
--- a/src/Microsoft.AspNet.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.ApiExplorer/DefaultApiDescriptionProvider.cs
@@ -15,7 +15,6 @@ using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Template;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Options;
-using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.ApiExplorer
{
@@ -311,7 +310,7 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
// Walk through all 'filter' attributes in order, and allow each one to see or override
// the results of the previous ones. This is similar to the execution path for content-negotiation.
- var contentTypes = new List();
+ var contentTypes = new MediaTypeCollection();
if (responseMetadataAttributes != null)
{
foreach (var metadataAttribute in responseMetadataAttributes)
@@ -322,7 +321,7 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
if (contentTypes.Count == 0)
{
- contentTypes.Add(null);
+ contentTypes.Add((string)null);
}
foreach (var contentType in contentTypes)
diff --git a/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseFormatMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseFormatMetadataProvider.cs
index 80c8c088ed..7bf083a0d8 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseFormatMetadataProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseFormatMetadataProvider.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.ApiExplorer
{
@@ -28,8 +27,8 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
/// The for which the supported content types are desired.
///
/// Content types which are supported by the .
- IReadOnlyList GetSupportedContentTypes(
- MediaTypeHeaderValue contentType,
+ IReadOnlyList GetSupportedContentTypes(
+ string contentType,
Type objectType);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseMetadataProvider.cs b/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseMetadataProvider.cs
index 5db0c96c93..d1addd7c60 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseMetadataProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ApiExplorer/IApiResponseMetadataProvider.cs
@@ -2,8 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Collections.Generic;
-using Microsoft.Net.Http.Headers;
+using Microsoft.AspNet.Mvc.Formatters;
namespace Microsoft.AspNet.Mvc.ApiExplorer
{
@@ -20,6 +19,6 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
///
/// Configures a collection of allowed content types which can be produced by the action.
///
- void SetContentTypes(IList contentTypes);
+ void SetContentTypes(MediaTypeCollection contentTypes);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/ConsumesAttribute.cs b/src/Microsoft.AspNet.Mvc.Core/ConsumesAttribute.cs
index 83ef895467..7b44014b56 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ConsumesAttribute.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ConsumesAttribute.cs
@@ -8,6 +8,8 @@ using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.ActionConstraints;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Filters;
+using Microsoft.AspNet.Mvc.Formatters;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
@@ -30,6 +32,15 @@ namespace Microsoft.AspNet.Mvc
throw new ArgumentNullException(nameof(contentType));
}
+ // We want to ensure that the given provided content types are valid values, so
+ // we validate them using the semantics of MediaTypeHeaderValue.
+ MediaTypeHeaderValue.Parse(contentType);
+
+ for (var i = 0; i < otherContentTypes.Length; i++)
+ {
+ MediaTypeHeaderValue.Parse(otherContentTypes[i]);
+ }
+
ContentTypes = GetContentTypes(contentType, otherContentTypes);
}
@@ -39,7 +50,7 @@ namespace Microsoft.AspNet.Mvc
int IActionConstraint.Order { get; } = ConsumesActionConstraintOrder;
///
- public IList ContentTypes { get; set; }
+ public MediaTypeCollection ContentTypes { get; set; }
///
public void OnResourceExecuting(ResourceExecutingContext context)
@@ -53,13 +64,12 @@ namespace Microsoft.AspNet.Mvc
// Ignore all other filters. This is to ensure we have a overriding behavior.
if (IsApplicable(context.ActionDescriptor))
{
- MediaTypeHeaderValue requestContentType = null;
- MediaTypeHeaderValue.TryParse(context.HttpContext.Request.ContentType, out requestContentType);
+ var requestContentType = context.HttpContext.Request.ContentType;
// Confirm the request's content type is more specific than a media type this action supports e.g. OK
// if client sent "text/plain" data and this action supports "text/*".
if (requestContentType != null &&
- !ContentTypes.Any(contentType => requestContentType.IsSubsetOf(contentType)))
+ !ContentTypes.Any(contentType => MediaTypeComparisons.IsSubsetOf(contentType, requestContentType)))
{
context.Result = new UnsupportedMediaTypeResult();
}
@@ -86,8 +96,7 @@ namespace Microsoft.AspNet.Mvc
return true;
}
- MediaTypeHeaderValue requestContentType = null;
- MediaTypeHeaderValue.TryParse(context.RouteContext.HttpContext.Request.ContentType, out requestContentType);
+ var requestContentType = context.RouteContext.HttpContext.Request.ContentType;
// If the request content type is null we need to act like pass through.
// In case there is a single candidate with a constraint it should be selected.
@@ -104,7 +113,7 @@ namespace Microsoft.AspNet.Mvc
// Confirm the request's content type is more specific than a media type this action supports e.g. OK
// if client sent "text/plain" data and this action supports "text/*".
- if (ContentTypes.Any(contentType => requestContentType.IsSubsetOf(contentType)))
+ if (ContentTypes.Any(contentType => MediaTypeComparisons.IsSubsetOf(contentType, requestContentType)))
{
return true;
}
@@ -164,22 +173,22 @@ namespace Microsoft.AspNet.Mvc
}
- private List GetContentTypes(string firstArg, string[] args)
+ private MediaTypeCollection GetContentTypes(string firstArg, string[] args)
{
var completeArgs = new List();
completeArgs.Add(firstArg);
completeArgs.AddRange(args);
- var contentTypes = new List();
+ var contentTypes = new MediaTypeCollection();
foreach (var arg in completeArgs)
{
- var contentType = MediaTypeHeaderValue.Parse(arg);
- if (contentType.MatchesAllSubTypes || contentType.MatchesAllTypes)
+ if (MediaTypeComparisons.MatchesAllSubtypes(arg) ||
+ MediaTypeComparisons.MatchesAllTypes(arg))
{
throw new InvalidOperationException(
Resources.FormatMatchAllContentTypeIsNotAllowed(arg));
}
- contentTypes.Add(contentType);
+ contentTypes.Add(arg);
}
return contentTypes;
diff --git a/src/Microsoft.AspNet.Mvc.Core/ContentResult.cs b/src/Microsoft.AspNet.Mvc.Core/ContentResult.cs
index 6af9614891..bef0fae947 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ContentResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ContentResult.cs
@@ -16,10 +16,10 @@ namespace Microsoft.AspNet.Mvc
{
public class ContentResult : ActionResult
{
- private readonly MediaTypeHeaderValue DefaultContentType = new MediaTypeHeaderValue("text/plain")
+ private readonly string DefaultContentType = new MediaTypeHeaderValue("text/plain")
{
Encoding = Encoding.UTF8
- };
+ }.ToString();
///
/// Gets or set the content representing the body of the response.
@@ -27,9 +27,9 @@ namespace Microsoft.AspNet.Mvc
public string Content { get; set; }
///
- /// Gets or sets the representing the Content-Type header of the response.
+ /// Gets or sets the Content-Type header for the response.
///
- public MediaTypeHeaderValue ContentType { get; set; }
+ public string ContentType { get; set; }
///
/// Gets or sets the HTTP status code.
diff --git a/src/Microsoft.AspNet.Mvc.Core/ControllerBase.cs b/src/Microsoft.AspNet.Mvc.Core/ControllerBase.cs
index 7e68bae65c..d76963088b 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ControllerBase.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ControllerBase.cs
@@ -271,7 +271,7 @@ namespace Microsoft.AspNet.Mvc
var result = new ContentResult
{
Content = content,
- ContentType = contentType
+ ContentType = contentType?.ToString()
};
return result;
diff --git a/src/Microsoft.AspNet.Mvc.Core/FileContentResult.cs b/src/Microsoft.AspNet.Mvc.Core/FileContentResult.cs
index c9745663ba..7022554aa4 100644
--- a/src/Microsoft.AspNet.Mvc.Core/FileContentResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/FileContentResult.cs
@@ -31,10 +31,6 @@ namespace Microsoft.AspNet.Mvc
{
throw new ArgumentNullException(nameof(fileContents));
}
- if (contentType == null)
- {
- throw new ArgumentNullException(nameof(contentType));
- }
}
///
@@ -45,18 +41,13 @@ namespace Microsoft.AspNet.Mvc
/// The bytes that represent the file contents.
/// The Content-Type header of the response.
public FileContentResult(byte[] fileContents, MediaTypeHeaderValue contentType)
- : base(contentType)
+ : base(contentType?.ToString())
{
if (fileContents == null)
{
throw new ArgumentNullException(nameof(fileContents));
}
- if (contentType == null)
- {
- throw new ArgumentNullException(nameof(contentType));
- }
-
FileContents = fileContents;
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/FileResult.cs b/src/Microsoft.AspNet.Mvc.Core/FileResult.cs
index 04bb55e48a..2413eb1096 100644
--- a/src/Microsoft.AspNet.Mvc.Core/FileResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/FileResult.cs
@@ -7,6 +7,7 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
@@ -24,7 +25,7 @@ namespace Microsoft.AspNet.Mvc
/// the provided .
///
/// The Content-Type header of the response.
- protected FileResult(MediaTypeHeaderValue contentType)
+ protected FileResult(string contentType)
{
if (contentType == null)
{
@@ -35,9 +36,9 @@ namespace Microsoft.AspNet.Mvc
}
///
- /// Gets the representing the Content-Type header of the response.
+ /// Gets the Content-Type header for the response.
///
- public MediaTypeHeaderValue ContentType { get; }
+ public string ContentType { get; }
///
/// Gets the file name that will be used in the Content-Disposition header of the response.
diff --git a/src/Microsoft.AspNet.Mvc.Core/FileStreamResult.cs b/src/Microsoft.AspNet.Mvc.Core/FileStreamResult.cs
index 8f31fce05c..ef65b8dc0a 100644
--- a/src/Microsoft.AspNet.Mvc.Core/FileStreamResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/FileStreamResult.cs
@@ -42,18 +42,13 @@ namespace Microsoft.AspNet.Mvc
/// The stream with the file.
/// The Content-Type header of the response.
public FileStreamResult(Stream fileStream, MediaTypeHeaderValue contentType)
- : base(contentType)
+ : base(contentType?.ToString())
{
if (fileStream == null)
{
throw new ArgumentNullException(nameof(fileStream));
}
- if (contentType == null)
- {
- throw new ArgumentNullException(nameof(contentType));
- }
-
FileStream = fileStream;
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatFilter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatFilter.cs
index 7bf4f07299..b64bc64d9f 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatFilter.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatFilter.cs
@@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNet.Mvc.ApiExplorer;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.Extensions.Options;
-using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Formatters
{
@@ -78,7 +76,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Determine media types this action supports.
var responseTypeFilters = context.Filters.OfType();
- var supportedMediaTypes = new List();
+ var supportedMediaTypes = new MediaTypeCollection();
foreach (var filter in responseTypeFilters)
{
filter.SetContentTypes(supportedMediaTypes);
@@ -91,7 +89,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// request's format and IApiResponseMetadataProvider-provided content types similarly to an Accept
// header and an output formatter's SupportedMediaTypes: Confirm action supports a more specific media
// type than requested e.g. OK if "text/*" requested and action supports "text/plain".
- if (!supportedMediaTypes.Any(c => c.IsSubsetOf(contentType)))
+ if (!supportedMediaTypes.Any(c => MediaTypeComparisons.IsSubsetOf(contentType, c)))
{
context.Result = new HttpNotFoundResult();
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatterMappings.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatterMappings.cs
index e7b0b70ac5..518864dbf6 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatterMappings.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/FormatterMappings.cs
@@ -4,24 +4,46 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Core;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Formatters
{
///
- /// Used to specify mapping between the URL Format and corresponding .
+ /// Used to specify mapping between the URL Format and corresponding media type.
///
public class FormatterMappings
{
- private readonly Dictionary _map =
- new Dictionary(StringComparer.OrdinalIgnoreCase);
+ private readonly Dictionary _map =
+ new Dictionary(StringComparer.OrdinalIgnoreCase);
///
- /// Sets mapping for the format to specified .
- /// If the format already exists, the will be overwritten with the new value.
+ /// Sets mapping for the format to specified media type.
+ /// If the format already exists, the media type will be overwritten with the new value.
///
/// The format value.
- /// The for the format value.
+ /// The media type for the format value.
+ public void SetMediaTypeMappingForFormat(string format, string contentType)
+ {
+ if (format == null)
+ {
+ throw new ArgumentNullException(nameof(format));
+ }
+
+ if (contentType == null)
+ {
+ throw new ArgumentNullException(nameof(contentType));
+ }
+
+ SetMediaTypeMappingForFormat(format, MediaTypeHeaderValue.Parse(contentType));
+ }
+
+ ///
+ /// Sets mapping for the format to specified media type.
+ /// If the format already exists, the media type will be overwritten with the new value.
+ ///
+ /// The format value.
+ /// The media type for the format value.
public void SetMediaTypeMappingForFormat(string format, MediaTypeHeaderValue contentType)
{
if (format == null)
@@ -36,31 +58,34 @@ namespace Microsoft.AspNet.Mvc.Formatters
ValidateContentType(contentType);
format = RemovePeriodIfPresent(format);
- _map[format] = contentType.CopyAsReadOnly();
+ _map[format] = contentType.ToString();
}
///
- /// Gets for the specified format.
+ /// Gets the media type for the specified format.
///
/// The format value.
- /// The for input format.
- public MediaTypeHeaderValue GetMediaTypeMappingForFormat(string format)
+ /// The media type for input format.
+ public string GetMediaTypeMappingForFormat(string format)
{
- if (format == null)
+ if (string.IsNullOrEmpty(format))
{
- throw new ArgumentNullException(nameof(format));
+ var message = Resources.FormatFormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat(
+ nameof(format));
+
+ throw new ArgumentException(message, nameof(format));
}
format = RemovePeriodIfPresent(format);
- MediaTypeHeaderValue value = null;
+ string value = null;
_map.TryGetValue(format, out value);
return value;
}
///
- /// Clears the mapping for the format.
+ /// Clears the media type mapping for the format.
///
/// The format value.
/// true if the format is successfully found and cleared; otherwise, false.
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/InputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/InputFormatter.cs
index a6fd215ef0..7330c0ef9d 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Formatters/InputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/InputFormatter.cs
@@ -8,6 +8,7 @@ using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Core;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Formatters
@@ -37,10 +38,10 @@ namespace Microsoft.AspNet.Mvc.Formatters
public IList SupportedEncodings { get; } = new List();
///
- /// Gets the mutable collection of elements supported by
+ /// Gets the mutable collection of media type elements supported by
/// this .
///
- public IList SupportedMediaTypes { get; } = new List();
+ public MediaTypeCollection SupportedMediaTypes { get; } = new MediaTypeCollection();
protected object GetDefaultValueForType(Type modelType)
{
@@ -61,8 +62,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
var contentType = context.HttpContext.Request.ContentType;
- MediaTypeHeaderValue requestContentType;
- if (!MediaTypeHeaderValue.TryParse(contentType, out requestContentType))
+ if (string.IsNullOrEmpty(contentType))
{
return false;
}
@@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// client sent "text/plain" data and this formatter supports "text/*".
return SupportedMediaTypes.Any(supportedMediaType =>
{
- return requestContentType.IsSubsetOf(supportedMediaType);
+ return MediaTypeComparisons.IsSubsetOf(supportedMediaType, contentType);
});
}
@@ -107,27 +107,28 @@ namespace Microsoft.AspNet.Mvc.Formatters
///
/// Returns an based on 's
- /// .
+ /// character set.
///
/// The .
///
/// An based on 's
- /// . null if no supported encoding was found.
+ /// character set. null if no supported encoding was found.
///
protected Encoding SelectCharacterEncoding(InputFormatterContext context)
{
var request = context.HttpContext.Request;
- MediaTypeHeaderValue contentType;
- MediaTypeHeaderValue.TryParse(request.ContentType, out contentType);
- if (contentType != null)
+ if (request.ContentType != null)
{
- var charset = contentType.Charset;
- if (!string.IsNullOrEmpty(charset))
+ var encoding = MediaTypeEncoding.GetEncoding(request.ContentType);
+ if (encoding != null)
{
foreach (var supportedEncoding in SupportedEncodings)
{
- if (string.Equals(charset, supportedEncoding.WebName, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(
+ encoding.WebName,
+ supportedEncoding.WebName,
+ StringComparison.OrdinalIgnoreCase))
{
return supportedEncoding;
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeCollection.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeCollection.cs
new file mode 100644
index 0000000000..8af4c214eb
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeCollection.cs
@@ -0,0 +1,73 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.ObjectModel;
+using Microsoft.Net.Http.Headers;
+
+namespace Microsoft.AspNet.Mvc.Formatters
+{
+ ///
+ /// A collection of media types.
+ ///
+ public class MediaTypeCollection : Collection
+ {
+ ///
+ /// Initializes a new instance of .
+ ///
+ public MediaTypeCollection()
+ {
+ }
+
+ ///
+ /// Adds an object to the end of the .
+ ///
+ /// The media type to be added to the end of the .
+ public void Add(MediaTypeHeaderValue item)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException(nameof(item));
+ }
+
+ Add(item.ToString());
+ }
+
+ ///
+ /// Inserts an element into the at the specified index.
+ ///
+ /// The zero-based index at which should be inserted.
+ /// The media type to insert.
+ public void Insert(int index, MediaTypeHeaderValue item)
+ {
+ if (index < 0 || index > Count)
+ {
+ throw new ArgumentOutOfRangeException(nameof(index));
+ }
+
+ if (item == null)
+ {
+ throw new ArgumentNullException(nameof(item));
+ }
+
+ Insert(index, item.ToString());
+ }
+
+ ///
+ /// Removes the first occurrence of a specific media type from the .
+ ///
+ ///
+ /// true if is successfully removed; otherwise, false.
+ /// This method also returns false if was not found in the original
+ /// .
+ public bool Remove(MediaTypeHeaderValue item)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException(nameof(item));
+ }
+
+ return Remove(item.ToString());
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeComparisons.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeComparisons.cs
new file mode 100644
index 0000000000..33775d5ff4
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeComparisons.cs
@@ -0,0 +1,120 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using Microsoft.Extensions.Primitives;
+using Microsoft.Net.Http.Headers;
+
+namespace Microsoft.AspNet.Mvc.Formatters
+{
+ ///
+ /// Different types of tests against media type values.
+ ///
+ public static class MediaTypeComparisons
+ {
+ ///
+ /// Determines if the media type is a subset of the media type
+ /// without taking into account the quality parameter.
+ ///
+ /// The more general media type.
+ /// The more specific media type.
+ /// true if is a more general media type than ;
+ /// otherwise false.
+ public static bool IsSubsetOf(StringSegment set, string subset)
+ {
+ return IsSubsetOf(set, new StringSegment(subset));
+ }
+
+ ///
+ /// Determines if the media type is a subset of the media type
+ /// without taking into account the quality parameter.
+ ///
+ /// The more general media type.
+ /// The more specific media type.
+ /// true if is a more general media type than ;
+ /// otherwise false.
+ public static bool IsSubsetOf(string set, string subset)
+ {
+ return IsSubsetOf(new StringSegment(set), new StringSegment(subset));
+ }
+
+ ///
+ /// Determines if the media type is a subset of the media type.
+ /// Two media types are compatible if one is a subset of the other ignoring any charset
+ /// parameter.
+ ///
+ /// The more general media type.
+ /// The more specific media type.
+ /// Whether or not we should skip checking the quality parameter.
+ /// true if is a more general media type than ;
+ /// otherwise false.
+ public static bool IsSubsetOf(StringSegment set, StringSegment subset)
+ {
+ if (!set.HasValue || !subset.HasValue)
+ {
+ return false;
+ }
+
+ MediaTypeHeaderValue setMediaType;
+ MediaTypeHeaderValue subSetMediaType;
+
+ return MediaTypeHeaderValue.TryParse(set.Value, out setMediaType) &&
+ MediaTypeHeaderValue.TryParse(subset.Value, out subSetMediaType) &&
+ subSetMediaType.IsSubsetOf(setMediaType);
+ }
+
+ ///
+ /// Determines if the type of a given matches all types, E.g, */*.
+ ///
+ /// The media type to check
+ /// true if the matches all subtypes; otherwise false.
+ public static bool MatchesAllTypes(string mediaType)
+ {
+ return MatchesAllTypes(new StringSegment(mediaType));
+ }
+
+ ///
+ /// Determines if the type of a given matches all types, E.g, */*.
+ ///
+ /// The media type to check
+ /// true if the matches all subtypes; otherwise false.
+ public static bool MatchesAllTypes(StringSegment mediaType)
+ {
+ if (!mediaType.HasValue)
+ {
+ return false;
+ }
+
+ MediaTypeHeaderValue parsedMediaType;
+ return MediaTypeHeaderValue.TryParse(mediaType.Value, out parsedMediaType) &&
+ parsedMediaType.MatchesAllTypes;
+ }
+
+ ///
+ /// Determines if the given matches all subtypes, E.g, text/*.
+ ///
+ /// The media type to check
+ /// true if the matches all subtypes; otherwise false.
+ public static bool MatchesAllSubtypes(string mediaType)
+ {
+ return MatchesAllSubtypes(new StringSegment(mediaType));
+ }
+
+ ///
+ /// Determines if the given matches all subtypes, E.g, text/*.
+ ///
+ /// The media type to check
+ /// true if the matches all subtypes; otherwise false.
+ public static bool MatchesAllSubtypes(StringSegment mediaType)
+ {
+ if (!mediaType.HasValue)
+ {
+ return false;
+ }
+
+ MediaTypeHeaderValue parsedMediaType;
+ return MediaTypeHeaderValue.TryParse(mediaType.Value, out parsedMediaType) &&
+ parsedMediaType.MatchesAllSubTypes;
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeEncoding.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeEncoding.cs
new file mode 100644
index 0000000000..a8da6ae7a1
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeEncoding.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Text;
+using Microsoft.Extensions.Primitives;
+using Microsoft.Net.Http.Headers;
+
+namespace Microsoft.AspNet.Mvc.Formatters
+{
+ ///
+ /// A set of operations to manipulate the encoding of a media type value.
+ ///
+ public class MediaTypeEncoding
+ {
+ ///
+ /// Gets the for the given if it exists.
+ ///
+ /// The media type from which to get the charset parameter.
+ /// The of the media type if it exists; otherwise null.
+ public static Encoding GetEncoding(StringSegment mediaType)
+ {
+ var charset = GetCharsetParameter(mediaType);
+ return GetEncodingFromCharset(charset);
+ }
+
+ ///
+ /// Gets the for the given if it exists.
+ ///
+ /// The media type from which to get the charset parameter.
+ /// The of the media type if it exists or a without value if not.
+ public static Encoding GetEncoding(string mediaType)
+ {
+ var charset = GetCharsetParameter(new StringSegment(mediaType));
+ return GetEncodingFromCharset(charset);
+ }
+
+ ///
+ /// Gets the charset parameter of the given if it exists.
+ ///
+ /// The media type from which to get the charset parameter.
+ /// The charset of the media type if it exists or a without value if not.
+ public static StringSegment GetCharsetParameter(StringSegment mediaType)
+ {
+ MediaTypeHeaderValue parsedMediaType;
+ if (MediaTypeHeaderValue.TryParse(mediaType.Value, out parsedMediaType))
+ {
+ return new StringSegment(parsedMediaType.Charset);
+ }
+ return new StringSegment();
+ }
+
+ ///
+ /// Replaces the encoding of the given with the provided
+ /// .
+ ///
+ /// The media type whose encoding will be replaced.
+ /// The encoding that will replace the encoding in the
+ /// A media type with the replaced encoding.
+ public static string ReplaceEncoding(string mediaType, Encoding encoding)
+ {
+ return ReplaceEncoding(new StringSegment(mediaType), encoding);
+ }
+
+ ///
+ /// Replaces the encoding of the given with the provided
+ /// .
+ ///
+ /// The media type whose encoding will be replaced.
+ /// The encoding that will replace the encoding in the
+ /// A media type with the replaced encoding.
+ public static string ReplaceEncoding(StringSegment mediaType, Encoding encoding)
+ {
+ var parsedMediaType = MediaTypeHeaderValue.Parse(mediaType.Value);
+ parsedMediaType.Encoding = encoding;
+
+ return parsedMediaType.ToString();
+ }
+
+ private static Encoding GetEncodingFromCharset(StringSegment charset)
+ {
+ if (charset.Equals("utf-8", StringComparison.OrdinalIgnoreCase))
+ {
+ // This is an optimization for utf-8 that prevents the Substring caused by
+ // charset.Value
+ return Encoding.UTF8;
+ }
+
+ try
+ {
+ // charset.Value might be an invalid encoding name as in charset=invalid.
+ // For that reason, we catch the exception thrown by Encoding.GetEncoding
+ // and return null instead.
+ return charset.HasValue ? Encoding.GetEncoding(charset.Value) : null;
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeSegmentWithQuality.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeSegmentWithQuality.cs
new file mode 100644
index 0000000000..16f06fd876
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/MediaTypeSegmentWithQuality.cs
@@ -0,0 +1,41 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.Extensions.Primitives;
+
+namespace Microsoft.AspNet.Mvc.Formatters
+{
+ ///
+ /// A media type with its associated quality.
+ ///
+ public struct MediaTypeSegmentWithQuality
+ {
+ ///
+ /// Initializes an instance of .
+ ///
+ /// The containing the media type.
+ /// The quality parameter of the media type or 1 in the case it does not exist.
+ public MediaTypeSegmentWithQuality(StringSegment mediaType, double quality)
+ {
+ MediaType = mediaType;
+ Quality = quality;
+ }
+
+ ///
+ /// Gets the media type of this .
+ ///
+ public StringSegment MediaType { get; }
+
+ ///
+ /// Gets the quality of this .
+ ///
+ public double Quality { get; }
+
+ ///
+ public override string ToString()
+ {
+ // For logging purposes
+ return MediaType.ToString();
+ }
+ }
+}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs
index 7863a8a498..41a8d9e57d 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/OutputFormatter.cs
@@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ApiExplorer;
using Microsoft.AspNet.Mvc.Core;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Formatters
@@ -17,16 +18,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
///
public abstract class OutputFormatter : IOutputFormatter, IApiResponseFormatMetadataProvider
{
- // using a field so we can return it as both IList and IReadOnlyList
- private readonly List _supportedMediaTypes;
-
///
/// Initializes a new instance of the class.
///
protected OutputFormatter()
{
SupportedEncodings = new List();
- _supportedMediaTypes = new List();
+ SupportedMediaTypes = new MediaTypeCollection();
}
///
@@ -37,13 +35,10 @@ namespace Microsoft.AspNet.Mvc.Formatters
public IList SupportedEncodings { get; }
///
- /// Gets the mutable collection of elements supported by
+ /// Gets the mutable collection of media type elements supported by
/// this .
///
- public IList SupportedMediaTypes
- {
- get { return _supportedMediaTypes; }
- }
+ public MediaTypeCollection SupportedMediaTypes { get; }
///
/// Returns a value indicating whether or not the given type can be written by this serializer.
@@ -56,8 +51,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
///
- public virtual IReadOnlyList GetSupportedContentTypes(
- MediaTypeHeaderValue contentType,
+ public virtual IReadOnlyList GetSupportedContentTypes(
+ string contentType,
Type objectType)
{
if (!CanWriteType(objectType))
@@ -68,21 +63,21 @@ namespace Microsoft.AspNet.Mvc.Formatters
if (contentType == null)
{
// If contentType is null, then any type we support is valid.
- return _supportedMediaTypes.Count > 0 ? _supportedMediaTypes : null;
+ return SupportedMediaTypes.Count > 0 ? SupportedMediaTypes : null;
}
else
{
- List mediaTypes = null;
+ List mediaTypes = null;
// Confirm this formatter supports a more specific media type than requested e.g. OK if "text/*"
// requested and formatter supports "text/plain". Treat contentType like it came from an Accept header.
- foreach (var mediaType in _supportedMediaTypes)
+ foreach (var mediaType in SupportedMediaTypes)
{
- if (mediaType.IsSubsetOf(contentType))
+ if (MediaTypeComparisons.IsSubsetOf(new StringSegment(contentType), mediaType))
{
if (mediaTypes == null)
{
- mediaTypes = new List();
+ mediaTypes = new List();
}
mediaTypes.Add(mediaType);
@@ -114,15 +109,19 @@ namespace Microsoft.AspNet.Mvc.Formatters
return encoding;
}
- var charset = context.ContentType?.Charset;
- if (charset != null)
+ if (context.ContentType.HasValue)
{
- for (var i = 0; i < SupportedEncodings.Count; i++)
+ var contentTypeEncoding = MediaTypeEncoding.GetCharsetParameter(context.ContentType);
+ if (contentTypeEncoding.HasValue)
{
- if (string.Equals(charset, SupportedEncodings[i].WebName, StringComparison.OrdinalIgnoreCase))
+ for (var i = 0; i < SupportedEncodings.Count; i++)
{
- // This is supported.
- return context.ContentType.Encoding;
+ var supportedEncoding = SupportedEncodings[i];
+ if (contentTypeEncoding.Equals(supportedEncoding.WebName, StringComparison.OrdinalIgnoreCase))
+ {
+ // This is supported.
+ return SupportedEncodings[i];
+ }
}
}
}
@@ -138,19 +137,19 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
throw new ArgumentNullException(nameof(context));
}
-
+
if (!CanWriteType(context.ObjectType))
{
return false;
}
-
- if (context.ContentType == null)
+
+ if (!context.ContentType.HasValue)
{
// If the desired content type is set to null, then the current formatter can write anything
// it wants.
if (SupportedMediaTypes.Count > 0)
{
- context.ContentType = SupportedMediaTypes[0];
+ context.ContentType = new StringSegment(SupportedMediaTypes[0]);
return true;
}
else
@@ -163,12 +162,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Confirm this formatter supports a more specific media type than requested e.g. OK if "text/*"
// requested and formatter supports "text/plain". contentType is typically what we got in an Accept
// header.
+ var contentType = context.ContentType;
for (var i = 0; i < SupportedMediaTypes.Count; i++)
{
- var mediaType = SupportedMediaTypes[i];
- if (mediaType.IsSubsetOf(context.ContentType))
+ var supportedMediaType = SupportedMediaTypes[i];
+ if (MediaTypeComparisons.IsSubsetOf(contentType, supportedMediaType))
{
- context.ContentType = mediaType;
+ context.ContentType = new StringSegment(SupportedMediaTypes[i]);
return true;
}
}
@@ -186,12 +186,12 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
var selectedMediaType = context.ContentType;
- if (selectedMediaType == null)
+ if (!selectedMediaType.HasValue)
{
// If content type is not set then set it based on supported media types.
if (SupportedEncodings.Count > 0)
{
- selectedMediaType = SupportedMediaTypes[0];
+ selectedMediaType = new StringSegment(SupportedMediaTypes[0]);
}
else
{
@@ -199,9 +199,6 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
}
- // Copy the media type as it may be a 'frozen' instance.
- selectedMediaType = selectedMediaType.Copy();
-
// Note: Text-based media types will use an encoding/charset - binary formats just ignore it. We want to
// make this class work with media types that use encodings, and those that don't.
//
@@ -215,7 +212,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
if (selectedEncoding != null)
{
// Override the content type value even if one already existed.
- selectedMediaType.Encoding = selectedEncoding;
+ var mediaTypeWithCharset = GetMediaTypeWithCharset(selectedMediaType.Value, selectedEncoding);
+ selectedMediaType = new StringSegment(mediaTypeWithCharset);
}
context.ContentType = selectedMediaType;
@@ -236,7 +234,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
var response = context.HttpContext.Response;
- response.ContentType = context.ContentType?.ToString();
+ response.ContentType = context.ContentType.Value;
}
///
@@ -246,6 +244,33 @@ namespace Microsoft.AspNet.Mvc.Formatters
/// A task which can write the response body.
public abstract Task WriteResponseBodyAsync(OutputFormatterWriteContext context);
+ ///
+ /// Adds or replaces the charset parameter in a given with the
+ /// given .
+ ///
+ /// The with the media type.
+ ///
+ /// The to add or replace in the .
+ ///
+ /// The mediaType with the given encoding.
+ protected string GetMediaTypeWithCharset(string mediaType, Encoding encoding)
+ {
+ var mediaTypeEncoding = MediaTypeEncoding.GetEncoding(mediaType);
+ if (mediaTypeEncoding == encoding)
+ {
+ return mediaType;
+ }
+ else if (mediaTypeEncoding == null)
+ {
+ return CreateMediaTypeWithEncoding(mediaType, encoding);
+ }
+ else
+ {
+ // This can happen if the user has overriden SelectCharacterEncoding
+ return MediaTypeEncoding.ReplaceEncoding(mediaType, encoding);
+ }
+ }
+
private Encoding MatchAcceptCharacterEncoding(IList acceptCharsetHeaders)
{
if (acceptCharsetHeaders != null && acceptCharsetHeaders.Count > 0)
@@ -329,5 +354,15 @@ namespace Microsoft.AspNet.Mvc.Formatters
sorted.Reverse();
return sorted;
}
+
+ private static string CreateMediaTypeWithEncoding(string mediaType, Encoding encoding)
+ {
+ return CreateMediaTypeWithEncoding(new StringSegment(mediaType), encoding);
+ }
+
+ private static string CreateMediaTypeWithEncoding(StringSegment mediaType, Encoding encoding)
+ {
+ return $"{mediaType.Value}; charset={encoding.WebName}";
+ }
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Formatters/StringOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Core/Formatters/StringOutputFormatter.cs
index 0d8b335189..a8d0265096 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Formatters/StringOutputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Formatters/StringOutputFormatter.cs
@@ -6,6 +6,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Internal;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Formatters
@@ -19,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
SupportedEncodings.Add(Encoding.UTF8);
SupportedEncodings.Add(Encoding.Unicode);
- SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain").CopyAsReadOnly());
+ SupportedMediaTypes.Add("text/plain");
}
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
@@ -33,7 +34,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// always return it as a text/plain format.
if (context.ObjectType == typeof(string) || context.Object is string)
{
- context.ContentType = SupportedMediaTypes[0];
+ context.ContentType = new StringSegment(SupportedMediaTypes[0]);
return true;
}
@@ -55,7 +56,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
var response = context.HttpContext.Response;
- return response.WriteAsync(valueAsString, context.ContentType?.Encoding ?? Encoding.UTF8);
+ return response.WriteAsync(
+ valueAsString,
+ MediaTypeEncoding.GetEncoding(context.ContentType) ?? Encoding.UTF8);
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs
index 5ce9702056..2f6cee1935 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Infrastructure/ObjectResultExecutor.cs
@@ -13,6 +13,7 @@ using Microsoft.AspNet.Mvc.Internal;
using Microsoft.AspNet.Mvc.Logging;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Infrastructure
@@ -98,10 +99,10 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
{
if (result.ContentTypes == null)
{
- result.ContentTypes = new List();
+ result.ContentTypes = new MediaTypeCollection();
}
- result.ContentTypes.Add(MediaTypeHeaderValue.Parse(responseContentType));
+ result.ContentTypes.Add(responseContentType);
}
}
@@ -157,7 +158,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
///
protected virtual IOutputFormatter SelectFormatter(
OutputFormatterWriteContext formatterContext,
- IList contentTypes,
+ MediaTypeCollection contentTypes,
IList formatters)
{
if (formatterContext == null)
@@ -185,14 +186,14 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
}
var request = formatterContext.HttpContext.Request;
- var acceptValues = PrepareAcceptValues(request.GetTypedHeaders().Accept);
+ var mediaTypes = GetMediaTypes(contentTypes, request);
IOutputFormatter selectedFormatter = null;
- if (contentTypes == null || contentTypes.Count == 0)
+ if (contentTypes.Count == 0)
{
// Check if we have enough information to do content-negotiation, otherwise get the first formatter
// which can write the type. Let the formatter choose the Content-Type.
- if (acceptValues == null || acceptValues.Count == 0)
+ if (!(mediaTypes.Count > 0))
{
Logger.NoAcceptForNegotiation();
@@ -207,13 +208,13 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
selectedFormatter = SelectFormatterUsingSortedAcceptHeaders(
formatterContext,
formatters,
- acceptValues);
+ mediaTypes);
// 2. No formatter was found based on Accept header. Fallback to the first formatter which can write
// the type. Let the formatter choose the Content-Type.
if (selectedFormatter == null)
{
- Logger.NoFormatterFromNegotiation(acceptValues);
+ Logger.NoFormatterFromNegotiation(mediaTypes);
// Set this flag to indicate that content-negotiation has failed to let formatters decide
// if they want to write the response or not.
@@ -224,32 +225,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
}
else
{
- if (acceptValues != null && acceptValues.Count > 0)
+ if (mediaTypes.Count > 0)
{
- // Filter and remove accept headers which cannot support any of the user specified content types.
- // That is, confirm this result supports a more specific media type than requested e.g. OK if
- // "text/*" requested and result supports "text/plain".
- for (var i = acceptValues.Count - 1; i >= 0; i--)
- {
- var isCompatible = false;
- for (var j = 0; j < contentTypes.Count; j++)
- {
- if (contentTypes[j].IsSubsetOf(acceptValues[i]))
- {
- isCompatible = true;
- }
- }
-
- if (!isCompatible)
- {
- acceptValues.RemoveAt(i);
- }
- }
-
selectedFormatter = SelectFormatterUsingSortedAcceptHeaders(
formatterContext,
formatters,
- acceptValues);
+ mediaTypes);
}
if (selectedFormatter == null)
@@ -270,6 +251,58 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
return selectedFormatter;
}
+ private List GetMediaTypes(
+ MediaTypeCollection contentTypes,
+ HttpRequest request)
+ {
+ var result = new List();
+ var parsedHeaders = request.GetTypedHeaders().Accept;
+ for (var i = 0; i < parsedHeaders?.Count; i++)
+ {
+ result.Add(new MediaTypeSegmentWithQuality(
+ new StringSegment(parsedHeaders[i].ToString()),
+ parsedHeaders[i].Quality ?? 1.0));
+ }
+
+ for (var i = 0; i < result.Count; i++)
+ {
+ if (!RespectBrowserAcceptHeader &&
+ MediaTypeComparisons.MatchesAllTypes(result[i].MediaType) &&
+ MediaTypeComparisons.MatchesAllSubtypes(result[i].MediaType))
+ {
+ result.Clear();
+ return result;
+ }
+
+ if (!InAcceptableMediaTypes(result[i].MediaType, contentTypes))
+ {
+ result.RemoveAt(i);
+ }
+ }
+
+ result.Sort((left, right) => left.Quality > right.Quality ? -1 : (left.Quality == right.Quality ? 0 : 1));
+
+ return result;
+ }
+
+ private static bool InAcceptableMediaTypes(StringSegment mediaType, MediaTypeCollection acceptableMediaTypes)
+ {
+ if (acceptableMediaTypes.Count == 0)
+ {
+ return true;
+ }
+
+ for (int i = 0; i < acceptableMediaTypes.Count; i++)
+ {
+ if (MediaTypeComparisons.IsSubsetOf(mediaType, acceptableMediaTypes[i]))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
///
/// Selects the to write the response. The first formatter which
/// can write the response should be chosen without any consideration for content type.
@@ -297,7 +330,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
foreach (var formatter in formatters)
{
- formatterContext.ContentType = null;
+ formatterContext.ContentType = new StringSegment();
if (formatter.CanWriteResult(formatterContext))
{
return formatter;
@@ -324,7 +357,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
protected virtual IOutputFormatter SelectFormatterUsingSortedAcceptHeaders(
OutputFormatterWriteContext formatterContext,
IList formatters,
- IList sortedAcceptHeaders)
+ IList sortedAcceptHeaders)
{
if (formatterContext == null)
{
@@ -341,11 +374,13 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
throw new ArgumentNullException(nameof(sortedAcceptHeaders));
}
- foreach (var contentType in sortedAcceptHeaders)
+ for (var i = 0; i < sortedAcceptHeaders.Count; i++)
{
- foreach (var formatter in formatters)
+ var mediaType = sortedAcceptHeaders[i];
+ formatterContext.ContentType = mediaType.MediaType;
+ for(var j = 0;j < formatters.Count;j++)
{
- formatterContext.ContentType = contentType;
+ var formatter = formatters[j];
if (formatter.CanWriteResult(formatterContext))
{
return formatter;
@@ -373,7 +408,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
protected virtual IOutputFormatter SelectFormatterUsingAnyAcceptableContentType(
OutputFormatterWriteContext formatterContext,
IList formatters,
- IList acceptableContentTypes)
+ MediaTypeCollection acceptableContentTypes)
{
if (formatterContext == null)
{
@@ -394,7 +429,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
{
foreach (var contentType in acceptableContentTypes)
{
- formatterContext.ContentType = contentType;
+ formatterContext.ContentType = new StringSegment(contentType);
if (formatter.CanWriteResult(formatterContext))
{
return formatter;
@@ -405,90 +440,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
return null;
}
- // There's no allocation-free way to sort an IList so we're going to have to live with the
- // copy + insertion sort.
- private IList PrepareAcceptValues(IList values)
- {
- if (values == null || values.Count == 0)
- {
- return null;
- }
-
- // By default we want to ignore considering accept headers for content negotiation when
- // they have a media type like */* in them. Browsers typically have these media types.
- // In these cases we would want the first formatter in the list of output formatters to
- // write the response. This default behavior can be changed through options, so checking here.
- if (!RespectBrowserAcceptHeader)
- {
- for (var i = 0; i < values.Count; i++)
- {
- if (values[i].MatchesAllTypes)
- {
- return null;
- }
- }
- }
-
- // Degenerate case, we can avoid copying anything.
- if (values.Count == 1)
- {
- return values;
- }
-
- var sortNeeded = false;
- var count = 0;
-
- for (var i = 0; i < values.Count; i++)
- {
- var value = values[i];
- if (value.Quality == HeaderQuality.NoMatch)
- {
- // Exclude this one
- }
- else if (value.Quality != null)
- {
- count++;
- sortNeeded = true;
- }
- else
- {
- count++;
- }
- }
-
- if (!sortNeeded)
- {
- return values;
- }
-
- var sorted = new List(count);
- for (var i = 0; i < values.Count; i++)
- {
- var value = values[i];
- if (value.Quality == HeaderQuality.NoMatch)
- {
- // Exclude this one
- }
- else
- {
- var position = sorted.BinarySearch(value, MediaTypeHeaderValueComparer.QualityComparer);
- if (position >= 0)
- {
- sorted.Insert(position + 1, value);
- }
- else
- {
- sorted.Insert(~position, value);
- }
- }
- }
-
- // We want a descending sort, but BinarySearch does ascending
- sorted.Reverse();
- return sorted;
- }
-
- private void ValidateContentTypes(IList contentTypes)
+ private void ValidateContentTypes(MediaTypeCollection contentTypes)
{
if (contentTypes == null)
{
@@ -498,7 +450,8 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
for (var i = 0; i < contentTypes.Count; i++)
{
var contentType = contentTypes[i];
- if (contentType.MatchesAllTypes || contentType.MatchesAllSubTypes)
+ if (MediaTypeComparisons.MatchesAllTypes(contentType) ||
+ MediaTypeComparisons.MatchesAllSubtypes(contentType))
{
var message = Resources.FormatObjectResult_MatchAllContentType(
contentType,
diff --git a/src/Microsoft.AspNet.Mvc.Core/Internal/ResponseContentTypeHelper.cs b/src/Microsoft.AspNet.Mvc.Core/Internal/ResponseContentTypeHelper.cs
index b2397a8030..ab7b078d2f 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Internal/ResponseContentTypeHelper.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Internal/ResponseContentTypeHelper.cs
@@ -3,8 +3,7 @@
using System.Diagnostics;
using System.Text;
-using Microsoft.Net.Http.Headers;
-using Microsoft.AspNet.Http;
+using Microsoft.AspNet.Mvc.Formatters;
namespace Microsoft.AspNet.Mvc.Internal
{
@@ -30,44 +29,47 @@ namespace Microsoft.AspNet.Mvc.Internal
/// The content type to be used for the response content type header
/// Encoding to be used for writing the response
public static void ResolveContentTypeAndEncoding(
- MediaTypeHeaderValue actionResultContentType,
+ string actionResultContentType,
string httpResponseContentType,
- MediaTypeHeaderValue defaultContentType,
+ string defaultContentType,
out string resolvedContentType,
out Encoding resolvedContentTypeEncoding)
{
Debug.Assert(defaultContentType != null);
- Debug.Assert(defaultContentType.Encoding != null);
+
+ var defaultContentTypeEncoding = MediaTypeEncoding.GetEncoding(defaultContentType);
+ Debug.Assert(defaultContentTypeEncoding != null);
// 1. User sets the ContentType property on the action result
if (actionResultContentType != null)
{
- resolvedContentType = actionResultContentType.ToString();
- resolvedContentTypeEncoding = actionResultContentType.Encoding ?? defaultContentType.Encoding;
+ resolvedContentType = actionResultContentType;
+ var actionResultEncoding = MediaTypeEncoding.GetEncoding(actionResultContentType);
+ resolvedContentTypeEncoding = actionResultEncoding ?? defaultContentTypeEncoding;
return;
}
// 2. User sets the ContentType property on the http response directly
if (!string.IsNullOrEmpty(httpResponseContentType))
{
- MediaTypeHeaderValue mediaType;
- if (MediaTypeHeaderValue.TryParse(httpResponseContentType, out mediaType))
+ var mediaTypeEncoding = MediaTypeEncoding.GetEncoding(httpResponseContentType);
+ if (mediaTypeEncoding != null)
{
resolvedContentType = httpResponseContentType;
- resolvedContentTypeEncoding = mediaType.Encoding ?? defaultContentType.Encoding;
+ resolvedContentTypeEncoding = mediaTypeEncoding;
}
else
{
resolvedContentType = httpResponseContentType;
- resolvedContentTypeEncoding = defaultContentType.Encoding;
+ resolvedContentTypeEncoding = defaultContentTypeEncoding;
}
return;
}
// 3. Fall-back to the default content type
- resolvedContentType = defaultContentType.ToString();
- resolvedContentTypeEncoding = defaultContentType.Encoding;
+ resolvedContentType = defaultContentType;
+ resolvedContentTypeEncoding = defaultContentTypeEncoding;
}
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/Logging/ObjectResultExecutorLoggerExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/Logging/ObjectResultExecutorLoggerExtensions.cs
index ec968c0f65..8b1677efb8 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Logging/ObjectResultExecutorLoggerExtensions.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Logging/ObjectResultExecutorLoggerExtensions.cs
@@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Logging
@@ -16,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.Logging
private static readonly Action _formatterSelected;
private static readonly Action _skippedContentNegotiation;
private static readonly Action _noAcceptForNegotiation;
- private static readonly Action, Exception> _noFormatterFromNegotiation;
+ private static readonly Action, Exception> _noFormatterFromNegotiation;
static ObjectResultExecutorLoggerExtensions()
{
@@ -40,7 +41,7 @@ namespace Microsoft.AspNet.Mvc.Logging
LogLevel.Debug,
4,
"No information found on request to perform content negotiation.");
- _noFormatterFromNegotiation = LoggerMessage.Define>(
+ _noFormatterFromNegotiation = LoggerMessage.Define>(
LogLevel.Debug,
5,
"Could not find an output formatter based on content negotiation. Accepted types were ({AcceptTypes})");
@@ -67,9 +68,9 @@ namespace Microsoft.AspNet.Mvc.Logging
_formatterSelected(logger, outputFormatter, contentType, null);
}
- public static void SkippedContentNegotiation(this ILogger logger, MediaTypeHeaderValue contentType)
+ public static void SkippedContentNegotiation(this ILogger logger, string contentType)
{
- _skippedContentNegotiation(logger, Convert.ToString(contentType), null);
+ _skippedContentNegotiation(logger, contentType, null);
}
public static void NoAcceptForNegotiation(this ILogger logger)
@@ -77,7 +78,7 @@ namespace Microsoft.AspNet.Mvc.Logging
_noAcceptForNegotiation(logger, null, null);
}
- public static void NoFormatterFromNegotiation(this ILogger logger, IEnumerable acceptTypes)
+ public static void NoFormatterFromNegotiation(this ILogger logger, IList acceptTypes)
{
_noFormatterFromNegotiation(logger, acceptTypes, null);
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs b/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs
index 381e62d31a..512478ca00 100644
--- a/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/MvcOptions.cs
@@ -53,8 +53,7 @@ namespace Microsoft.AspNet.Mvc
public FilterCollection Filters { get; }
///
- /// Used to specify mapping between the URL Format and corresponding
- /// .
+ /// Used to specify mapping between the URL Format and corresponding media type.
///
public FormatterMappings FormatterMappings { get; }
diff --git a/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs b/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs
index e9f3eb3528..30d488548b 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ObjectResult.cs
@@ -2,12 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
-using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
@@ -17,14 +15,14 @@ namespace Microsoft.AspNet.Mvc
{
Value = value;
Formatters = new FormatterCollection();
- ContentTypes = new List();
+ ContentTypes = new MediaTypeCollection();
}
public object Value { get; set; }
public FormatterCollection Formatters { get; set; }
- public IList ContentTypes { get; set; }
+ public MediaTypeCollection ContentTypes { get; set; }
public Type DeclaredType { get; set; }
diff --git a/src/Microsoft.AspNet.Mvc.Core/PhysicalFileResult.cs b/src/Microsoft.AspNet.Mvc.Core/PhysicalFileResult.cs
index 6c343d3fef..70d2465f55 100644
--- a/src/Microsoft.AspNet.Mvc.Core/PhysicalFileResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/PhysicalFileResult.cs
@@ -34,10 +34,6 @@ namespace Microsoft.AspNet.Mvc
{
throw new ArgumentNullException(nameof(fileName));
}
- if (contentType == null)
- {
- throw new ArgumentNullException(nameof(contentType));
- }
}
///
@@ -47,18 +43,13 @@ namespace Microsoft.AspNet.Mvc
/// The path to the file. The path must be an absolute path.
/// The Content-Type header of the response.
public PhysicalFileResult(string fileName, MediaTypeHeaderValue contentType)
- : base(contentType)
+ : base(contentType?.ToString())
{
if (fileName == null)
{
throw new ArgumentNullException(nameof(fileName));
}
- if (contentType == null)
- {
- throw new ArgumentNullException(nameof(contentType));
- }
-
FileName = fileName;
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ProducesAttribute.cs b/src/Microsoft.AspNet.Mvc.Core/ProducesAttribute.cs
index a969c3fbb8..82fdb42719 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ProducesAttribute.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ProducesAttribute.cs
@@ -8,6 +8,7 @@ using Microsoft.AspNet.Mvc.ApiExplorer;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.Formatters;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
@@ -31,7 +32,7 @@ namespace Microsoft.AspNet.Mvc
}
Type = type;
- ContentTypes = new List();
+ ContentTypes = new MediaTypeCollection();
}
///
@@ -46,12 +47,21 @@ namespace Microsoft.AspNet.Mvc
throw new ArgumentNullException(nameof(contentType));
}
+ // We want to ensure that the given provided content types are valid values, so
+ // we validate them using the semantics of MediaTypeHeaderValue.
+ MediaTypeHeaderValue.Parse(contentType);
+
+ for (var i = 0; i < additionalContentTypes.Length; i++)
+ {
+ MediaTypeHeaderValue.Parse(additionalContentTypes[i]);
+ }
+
ContentTypes = GetContentTypes(contentType, additionalContentTypes);
}
public Type Type { get; set; }
- public IList ContentTypes { get; set; }
+ public MediaTypeCollection ContentTypes { get; set; }
public override void OnResultExecuting(ResultExecutingContext context)
{
@@ -74,16 +84,17 @@ namespace Microsoft.AspNet.Mvc
}
}
- private List GetContentTypes(string firstArg, string[] args)
+ private MediaTypeCollection GetContentTypes(string firstArg, string[] args)
{
var completeArgs = new List();
completeArgs.Add(firstArg);
completeArgs.AddRange(args);
- var contentTypes = new List();
+ var contentTypes = new MediaTypeCollection();
foreach (var arg in completeArgs)
{
- var contentType = MediaTypeHeaderValue.Parse(arg);
- if (contentType.MatchesAllSubTypes || contentType.MatchesAllTypes)
+ var contentType = arg;
+ if (MediaTypeComparisons.MatchesAllSubtypes(contentType)||
+ MediaTypeComparisons.MatchesAllTypes(contentType))
{
throw new InvalidOperationException(
Resources.FormatMatchAllContentTypeIsNotAllowed(arg));
@@ -95,7 +106,7 @@ namespace Microsoft.AspNet.Mvc
return contentTypes;
}
- public void SetContentTypes(IList contentTypes)
+ public void SetContentTypes(MediaTypeCollection contentTypes)
{
contentTypes.Clear();
foreach (var contentType in ContentTypes)
diff --git a/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs
index 2918a933b4..9307dd86d2 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/Properties/Resources.Designer.cs
@@ -1034,6 +1034,22 @@ namespace Microsoft.AspNet.Mvc.Core
return GetString("HttpResponseStreamWriter_StreamNotWritable");
}
+ ///
+ /// The argument '{0}' is invalid. Empty or null formats are not supported.
+ ///
+ internal static string FormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat
+ {
+ get { return GetString("FormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat"); }
+ }
+
+ ///
+ /// The argument '{0}' is invalid. Empty or null formats are not supported.
+ ///
+ internal static string FormatFormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat(object p0)
+ {
+ return string.Format(CultureInfo.CurrentCulture, GetString("FormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat"), p0);
+ }
+
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);
diff --git a/src/Microsoft.AspNet.Mvc.Core/Resources.resx b/src/Microsoft.AspNet.Mvc.Core/Resources.resx
index 4e9132532f..946db5d5f7 100644
--- a/src/Microsoft.AspNet.Mvc.Core/Resources.resx
+++ b/src/Microsoft.AspNet.Mvc.Core/Resources.resx
@@ -319,4 +319,7 @@
The stream must support writing.
+
+ The argument '{0}' is invalid. Empty or null formats are not supported.
+
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.Core/VirtualFileResult.cs b/src/Microsoft.AspNet.Mvc.Core/VirtualFileResult.cs
index 96a708c257..d60cdfd9c7 100644
--- a/src/Microsoft.AspNet.Mvc.Core/VirtualFileResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/VirtualFileResult.cs
@@ -37,10 +37,6 @@ namespace Microsoft.AspNet.Mvc
{
throw new ArgumentNullException(nameof(fileName));
}
- if (contentType == null)
- {
- throw new ArgumentNullException(nameof(contentType));
- }
}
///
@@ -51,18 +47,13 @@ namespace Microsoft.AspNet.Mvc
/// The path to the file. The path must be relative/virtual.
/// The Content-Type header of the response.
public VirtualFileResult(string fileName, MediaTypeHeaderValue contentType)
- : base(contentType)
+ : base(contentType?.ToString())
{
if (fileName == null)
{
throw new ArgumentNullException(nameof(fileName));
}
- if (contentType == null)
- {
- throw new ArgumentNullException(nameof(contentType));
- }
-
FileName = fileName;
}
diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/Infrastructure/JsonResultExecutor.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/Infrastructure/JsonResultExecutor.cs
index 3ba5ec62dc..e3bbf4ea8d 100644
--- a/src/Microsoft.AspNet.Mvc.Formatters.Json/Infrastructure/JsonResultExecutor.cs
+++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/Infrastructure/JsonResultExecutor.cs
@@ -18,10 +18,10 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
///
public class JsonResultExecutor
{
- private static readonly MediaTypeHeaderValue DefaultContentType = new MediaTypeHeaderValue("application/json")
+ private static readonly string DefaultContentType = new MediaTypeHeaderValue("application/json")
{
Encoding = Encoding.UTF8
- }.CopyAsReadOnly();
+ }.ToString();
///
/// Creates a new .
diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonOutputFormatter.cs
index efc69a30fa..6a927c3de7 100644
--- a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonOutputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonOutputFormatter.cs
@@ -140,7 +140,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
var response = context.HttpContext.Response;
- var selectedEncoding = context.ContentType?.Encoding ?? Encoding.UTF8;
+ var selectedEncoding = MediaTypeEncoding.GetEncoding(context.ContentType) ?? Encoding.UTF8;
using (var writer = context.WriterFactory(response.Body, selectedEncoding))
{
diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonResult.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonResult.cs
index 861335d8e6..8770a4de1e 100644
--- a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonResult.cs
+++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonResult.cs
@@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
///
/// Gets or sets the representing the Content-Type header of the response.
///
- public MediaTypeHeaderValue ContentType { get; set; }
+ public string ContentType { get; set; }
///
/// Gets or sets the .
diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlDataContractSerializerOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlDataContractSerializerOutputFormatter.cs
index 758652a3fe..e17638161d 100644
--- a/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlDataContractSerializerOutputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlDataContractSerializerOutputFormatter.cs
@@ -12,6 +12,7 @@ using System.Xml;
using Microsoft.AspNet.Mvc.Formatters.Xml;
using Microsoft.AspNet.Mvc.Formatters.Xml.Internal;
using Microsoft.AspNet.Mvc.Internal;
+using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Formatters
{
@@ -187,7 +188,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
var writerSettings = WriterSettings.Clone();
- writerSettings.Encoding = context.ContentType?.Encoding ?? Encoding.UTF8;
+ writerSettings.Encoding = MediaTypeEncoding.GetEncoding(context.ContentType) ?? Encoding.UTF8;
// Wrap the object only if there is a wrapping type.
var value = context.Object;
diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlSerializerOutputFormatter.cs b/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlSerializerOutputFormatter.cs
index bf088222f6..414de4d775 100644
--- a/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlSerializerOutputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Formatters.Xml/XmlSerializerOutputFormatter.cs
@@ -12,6 +12,7 @@ using System.Xml.Serialization;
using Microsoft.AspNet.Mvc.Formatters.Xml;
using Microsoft.AspNet.Mvc.Formatters.Xml.Internal;
using Microsoft.AspNet.Mvc.Internal;
+using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc.Formatters
{
@@ -164,7 +165,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
var response = context.HttpContext.Response;
var writerSettings = WriterSettings.Clone();
- writerSettings.Encoding = context.ContentType.Encoding ?? Encoding.UTF8;
+ writerSettings.Encoding = MediaTypeEncoding.GetEncoding(context.ContentType) ?? Encoding.UTF8;
// Wrap the object only if there is a wrapping type.
var value = context.Object;
diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/PartialViewResult.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/PartialViewResult.cs
index 3baf4a0505..b512bcd5c4 100644
--- a/src/Microsoft.AspNet.Mvc.ViewFeatures/PartialViewResult.cs
+++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/PartialViewResult.cs
@@ -46,9 +46,9 @@ namespace Microsoft.AspNet.Mvc
public IViewEngine ViewEngine { get; set; }
///
- /// Gets or sets the representing the Content-Type header of the response.
+ /// Gets or sets the Content-Type header for the response.
///
- public MediaTypeHeaderValue ContentType { get; set; }
+ public string ContentType { get; set; }
///
public override async Task ExecuteResultAsync(ActionContext context)
diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs
index de9cba9191..5a2a358cf8 100644
--- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs
+++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewComponentResult.cs
@@ -16,7 +16,6 @@ using Microsoft.AspNet.Mvc.ViewFeatures.Internal;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
-using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
@@ -31,9 +30,9 @@ namespace Microsoft.AspNet.Mvc
public object Arguments { get; set; }
///
- /// Gets or sets the representing the Content-Type header of the response.
+ /// Gets or sets the Content-Type header for the response.
///
- public MediaTypeHeaderValue ContentType { get; set; }
+ public string ContentType { get; set; }
///
/// Gets or sets the HTTP status code.
diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs
index f43c6587db..5ff35adc6f 100644
--- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs
+++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewFeatures/ViewExecutor.cs
@@ -23,12 +23,9 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
public class ViewExecutor
{
///
- /// The default content-type header value for views, text/html; charset=utf8.
+ /// The default content-type header value for views, text/html; charset=utf-8.
///
- public static readonly MediaTypeHeaderValue DefaultContentType = new MediaTypeHeaderValue("text/html")
- {
- Encoding = Encoding.UTF8
- }.CopyAsReadOnly();
+ public static readonly string DefaultContentType = "text/html; charset=utf-8";
///
/// Creates a new .
@@ -122,7 +119,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
IView view,
ViewDataDictionary viewData,
ITempDataDictionary tempData,
- MediaTypeHeaderValue contentType,
+ string contentType,
int? statusCode)
{
if (actionContext == null)
diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewResult.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewResult.cs
index ce6f04033f..3997081da5 100644
--- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewResult.cs
+++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ViewResult.cs
@@ -51,9 +51,9 @@ namespace Microsoft.AspNet.Mvc
public IViewEngine ViewEngine { get; set; }
///
- /// Gets or sets the representing the Content-Type header of the response.
+ /// Gets or sets the Content-Type header for the response.
///
- public MediaTypeHeaderValue ContentType { get; set; }
+ public string ContentType { get; set; }
///
public override async Task ExecuteResultAsync(ActionContext context)
diff --git a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs
index 9daa158e98..7d70486308 100644
--- a/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs
+++ b/src/Microsoft.AspNet.Mvc.WebApiCompatShim/ApiController.cs
@@ -409,10 +409,7 @@ namespace System.Web.Http
}
var result = new JsonResult(content, serializerSettings);
- result.ContentType = new MediaTypeHeaderValue("application/json")
- {
- Encoding = encoding
- };
+ result.ContentType = $"application/json; charset={encoding.WebName}";
return result;
}
diff --git a/test/Microsoft.AspNet.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs b/test/Microsoft.AspNet.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs
index ca8d57080c..5d22c25bd4 100644
--- a/test/Microsoft.AspNet.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ApiExplorer.Test/DefaultApiDescriptionProviderTest.cs
@@ -18,6 +18,7 @@ using Microsoft.AspNet.Mvc.Routing;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Constraints;
using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -1385,14 +1386,14 @@ namespace Microsoft.AspNet.Mvc.Description
{
public ContentTypeAttribute(string mediaType)
{
- ContentTypes.Add(MediaTypeHeaderValue.Parse(mediaType));
+ ContentTypes.Add(mediaType);
}
- public List ContentTypes { get; } = new List();
+ public MediaTypeCollection ContentTypes { get; } = new MediaTypeCollection();
public Type Type { get; set; }
- public void SetContentTypes(IList contentTypes)
+ public void SetContentTypes(MediaTypeCollection contentTypes)
{
contentTypes.Clear();
foreach (var contentType in ContentTypes)
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ContentResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ContentResultTest.cs
index 59614401e8..113cbd5c75 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ContentResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ContentResultTest.cs
@@ -9,6 +9,8 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.Formatters;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Mvc.ViewComponents;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
@@ -32,7 +34,7 @@ namespace Microsoft.AspNet.Mvc
ContentType = new MediaTypeHeaderValue("text/plain")
{
Encoding = Encoding.UTF7
- }
+ }.ToString()
};
var httpContext = GetHttpContext();
var actionContext = GetActionContext(httpContext);
@@ -41,7 +43,7 @@ namespace Microsoft.AspNet.Mvc
await contentResult.ExecuteResultAsync(actionContext);
// Assert
- Assert.Equal("text/plain; charset=utf-7", httpContext.Response.ContentType);
+ MediaTypeAssert.Equal("text/plain; charset=utf-7", httpContext.Response.ContentType);
}
[Fact]
@@ -55,7 +57,7 @@ namespace Microsoft.AspNet.Mvc
ContentType = new MediaTypeHeaderValue("text/plain")
{
Encoding = Encoding.ASCII
- }
+ }.ToString()
};
var httpContext = GetHttpContext();
httpContext.Features.Set(new TestBufferingFeature());
@@ -153,7 +155,7 @@ namespace Microsoft.AspNet.Mvc
var contentResult = new ContentResult
{
Content = content,
- ContentType = contentType
+ ContentType = contentType?.ToString()
};
var httpContext = GetHttpContext();
var memoryStream = new MemoryStream();
@@ -165,7 +167,8 @@ namespace Microsoft.AspNet.Mvc
await contentResult.ExecuteResultAsync(actionContext);
// Assert
- Assert.Equal(expectedContentType, httpContext.Response.ContentType);
+ var finalResponseContentType = httpContext.Response.ContentType;
+ Assert.Equal(expectedContentType, finalResponseContentType);
Assert.Equal(expectedContentData, memoryStream.ToArray());
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ControllerBaseTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerBaseTest.cs
index 4b2fa08023..c00f95e894 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ControllerBaseTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ControllerBaseTest.cs
@@ -10,8 +10,10 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
+using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing;
using Microsoft.Net.Http.Headers;
@@ -975,7 +977,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
// Assert
Assert.IsType(actualContentResult);
Assert.Equal("TestContent", actualContentResult.Content);
- Assert.Null(actualContentResult.ContentType.Encoding);
+ Assert.Null(MediaTypeEncoding.GetEncoding(actualContentResult.ContentType));
Assert.Equal("text/plain", actualContentResult.ContentType.ToString());
}
@@ -991,7 +993,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
// Assert
Assert.IsType(actualContentResult);
Assert.Equal("TestContent", actualContentResult.Content);
- Assert.Same(Encoding.UTF8, actualContentResult.ContentType.Encoding);
+ Assert.Same(Encoding.UTF8, MediaTypeEncoding.GetEncoding(actualContentResult.ContentType));
Assert.Equal("text/plain; charset=utf-8", actualContentResult.ContentType.ToString());
}
@@ -1024,7 +1026,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
Assert.NotNull(contentResult.ContentType);
Assert.Equal(contentType, contentResult.ContentType.ToString());
// The default encoding of ContentResult is used when this result is executed.
- Assert.Null(contentResult.ContentType.Encoding);
+ Assert.Null(MediaTypeEncoding.GetEncoding(contentResult.ContentType));
}
[Fact]
@@ -1032,13 +1034,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test
{
// Arrange
var contentController = new ContentController();
- var contentType = MediaTypeHeaderValue.Parse("text/xml; charset=us-ascii; p1=p1-value");
+ var contentType = "text/xml; charset=us-ascii; p1=p1-value";
// Act
var contentResult = (ContentResult)contentController.Content_WithEncodingInCharset_AndEncodingParameter();
// Assert
- Assert.Equal(contentType, contentResult.ContentType);
+ MediaTypeAssert.Equal(contentType, contentResult.ContentType);
}
[Fact]
@@ -1046,7 +1048,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test
{
// Arrange
var contentController = new ContentController();
- var contentType = MediaTypeHeaderValue.Parse("text/xml; charset=us-ascii; p1=p1-value");
+ var contentType = "text/xml; charset=us-ascii; p1=p1-value";
// Act
var contentResult = (ContentResult)contentController.Content_WithEncodingInCharset();
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/FileContentResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/FileContentResultTest.cs
index 3895f81cd8..487b6a5a7a 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/FileContentResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/FileContentResultTest.cs
@@ -7,11 +7,11 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
-using Microsoft.Net.Http.Headers;
using Xunit;
namespace Microsoft.AspNet.Mvc
@@ -37,14 +37,14 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var fileContents = new byte[0];
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
- var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
+ var expectedMediaType = contentType;
// Act
var result = new FileContentResult(fileContents, contentType);
// Assert
Assert.Same(fileContents, result.FileContents);
- Assert.Equal(expectedMediaType, result.ContentType);
+ MediaTypeAssert.Equal(expectedMediaType, result.ContentType);
}
[Fact]
@@ -83,7 +83,7 @@ namespace Microsoft.AspNet.Mvc
var context = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
- var result = new FileContentResult(buffer, MediaTypeHeaderValue.Parse(expectedContentType));
+ var result = new FileContentResult(buffer, expectedContentType);
// Act
await result.ExecuteResultAsync(context);
@@ -108,7 +108,7 @@ namespace Microsoft.AspNet.Mvc
var context = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
- var result = new FileContentResult(buffer, MediaTypeHeaderValue.Parse(expectedContentType));
+ var result = new FileContentResult(buffer, expectedContentType);
// Act
await result.ExecuteResultAsync(context);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/FileResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/FileResultTest.cs
index 75f9c4214c..a9aa1be90d 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/FileResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/FileResultTest.cs
@@ -274,12 +274,12 @@ namespace Microsoft.AspNet.Mvc
public bool WasWriteFileCalled;
public EmptyFileResult()
- : base(MediaTypeHeaderValue.Parse("application/octet"))
+ : base("application/octet")
{
}
public EmptyFileResult(string contentType)
- : base(MediaTypeHeaderValue.Parse(contentType))
+ : base(contentType)
{
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/FileStreamResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/FileStreamResultTest.cs
index 3e765b8d75..341a46bb82 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/FileStreamResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/FileStreamResultTest.cs
@@ -10,11 +10,11 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
-using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -41,14 +41,14 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var stream = Stream.Null;
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
- var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
+ var expectedMediaType = contentType;
// Act
var result = new FileStreamResult(stream, contentType);
// Assert
Assert.Equal(stream, result.FileStream);
- Assert.Equal(expectedMediaType, result.ContentType);
+ MediaTypeAssert.Equal(expectedMediaType, result.ContentType);
}
[Fact]
@@ -130,7 +130,7 @@ namespace Microsoft.AspNet.Mvc
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
- var result = new FileStreamResult(originalStream, MediaTypeHeaderValue.Parse(expectedContentType));
+ var result = new FileStreamResult(originalStream, expectedContentType);
// Act
await result.ExecuteResultAsync(actionContext);
@@ -157,7 +157,7 @@ namespace Microsoft.AspNet.Mvc
httpContext.Response.Body = outStream;
var actionContext = new ActionContext(httpContext, new RouteData(), new ActionDescriptor());
- var result = new FileStreamResult(originalStream, MediaTypeHeaderValue.Parse(expectedContentType));
+ var result = new FileStreamResult(originalStream, expectedContentType);
// Act
await result.ExecuteResultAsync(actionContext);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatFilterTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatFilterTest.cs
index ae39bbb995..c0c0a19717 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatFilterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatFilterTest.cs
@@ -4,9 +4,10 @@
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.Filters;
-using Microsoft.AspNet.Mvc.Infrastructure;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -32,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
string contentType)
{
// Arrange
- var mediaType = MediaTypeHeaderValue.Parse("application/json");
+ var mediaType = new StringSegment("application/json");
var mockObjects = new MockObjects(format, place);
var resultExecutingContext = mockObjects.CreateResultExecutingContext();
@@ -52,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Assert
var objectResult = Assert.IsType(resultExecutingContext.Result);
Assert.Equal(1, objectResult.ContentTypes.Count);
- AssertMediaTypesEqual(mediaType, objectResult.ContentTypes[0]);
+ MediaTypeAssert.Equal(mediaType, objectResult.ContentTypes[0]);
}
[Fact]
@@ -61,7 +62,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// If the format is present in both route and query data, the one in route data wins
// Arrange
- var mediaType = MediaTypeHeaderValue.Parse("application/json");
+ var mediaType = new StringSegment("application/json");
var mockObjects = new MockObjects("json", FormatSource.RouteData);
var httpContext = new Mock();
httpContext.Setup(c => c.Response).Returns(new Mock().Object);
@@ -95,7 +96,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Assert
var objectResult = Assert.IsType(resultExecutingContext.Result);
Assert.Equal(1, objectResult.ContentTypes.Count);
- AssertMediaTypesEqual(mediaType, objectResult.ContentTypes[0]);
+ MediaTypeAssert.Equal(mediaType, objectResult.ContentTypes[0]);
}
[Theory]
@@ -108,7 +109,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
string contentType)
{
// Arrange
- var mediaType = MediaTypeHeaderValue.Parse(contentType);
+ var mediaType = new StringSegment(contentType);
var mockObjects = new MockObjects(format, place);
var resultExecutingContext = mockObjects.CreateResultExecutingContext();
@@ -127,7 +128,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Assert
var objectResult = Assert.IsType(resultExecutingContext.Result);
Assert.Equal(1, objectResult.ContentTypes.Count);
- AssertMediaTypesEqual(mediaType, objectResult.ContentTypes[0]);
+ MediaTypeAssert.Equal(mediaType, objectResult.ContentTypes[0]);
}
[Theory]
@@ -303,7 +304,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
public void FormatFilter_ExplicitContentType_SetOnObjectResult_TakesPrecedence()
{
// Arrange
- var mediaType = MediaTypeHeaderValue.Parse("application/foo");
+ var mediaType = new StringSegment("application/foo");
var mockObjects = new MockObjects("json", FormatSource.QueryData);
var httpContext = new Mock();
httpContext.Setup(c => c.Response).Returns(new Mock().Object);
@@ -330,7 +331,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Assert
var result = Assert.IsType(resultExecutingContext.Result);
Assert.Equal(1, result.ContentTypes.Count);
- AssertMediaTypesEqual(mediaType, result.ContentTypes[0]);
+ MediaTypeAssert.Equal(mediaType, result.ContentTypes[0]);
}
[Fact]
@@ -366,21 +367,6 @@ namespace Microsoft.AspNet.Mvc.Formatters
Assert.Equal(0, result.ContentTypes.Count);
}
- private static void AssertMediaTypesEqual(
- MediaTypeHeaderValue expectedMediaType,
- MediaTypeHeaderValue actualMediaType)
- {
- Assert.Equal(expectedMediaType.MediaType, actualMediaType.MediaType);
- Assert.Equal(expectedMediaType.SubType, actualMediaType.SubType);
- Assert.Equal(expectedMediaType.Charset, actualMediaType.Charset);
- Assert.Equal(expectedMediaType.MatchesAllTypes, actualMediaType.MatchesAllTypes);
- Assert.Equal(expectedMediaType.MatchesAllSubTypes, actualMediaType.MatchesAllSubTypes);
- Assert.Equal(expectedMediaType.Parameters.Count, actualMediaType.Parameters.Count);
- foreach (var item in expectedMediaType.Parameters)
- {
- Assert.Equal(item.Value, NameValueHeaderValue.Find(actualMediaType.Parameters, item.Name).Value);
- }
- }
private class MockObjects
{
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatterMappingsTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatterMappingsTest.cs
index db35cbc6bf..47a37ef7d7 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatterMappingsTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/FormatterMappingsTest.cs
@@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using Microsoft.AspNet.Mvc.TestCommon;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Xunit;
@@ -10,33 +12,44 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
public class FormatterMappingsTest
{
+ [Theory]
+ [InlineData(null)]
+ [InlineData("")]
+ public void FormatterMappings_GetMediaTypeMappingForFormat_ThrowsForInvalidFormats(string format)
+ {
+ // Arrange
+ var options = new FormatterMappings();
+
+ // Act & Assert
+ Assert.Throws("format", () => options.GetMediaTypeMappingForFormat(format));
+ }
+
[Theory]
[InlineData(".xml", "application/xml", "xml")]
[InlineData("json", "application/json", "JSON")]
[InlineData(".foo", "text/foo", "Foo")]
[InlineData(".Json", "application/json", "json")]
- [InlineData("FOo", "text/foo", "FOO")]
+ [InlineData("FOo", "text/foo", "FOO")]
public void FormatterMappings_SetFormatMapping_DiffSetGetFormat(string setFormat, string contentType, string getFormat)
{
// Arrange
- var mediaType = MediaTypeHeaderValue.Parse(contentType);
var options = new FormatterMappings();
- options.SetMediaTypeMappingForFormat(setFormat, mediaType);
+ options.SetMediaTypeMappingForFormat(setFormat, MediaTypeHeaderValue.Parse(contentType));
// Act
var returnMediaType = options.GetMediaTypeMappingForFormat(getFormat);
// Assert
- Assert.Equal(mediaType, returnMediaType);
+ MediaTypeAssert.Equal(contentType, returnMediaType);
}
-
+
[Fact]
public void FormatterMappings_Invalid_Period()
{
// Arrange
var options = new FormatterMappings();
var format = ".";
- var expected = string.Format(@"The format provided is invalid '{0}'. A format must be a non-empty file-" +
+ var expected = string.Format(@"The format provided is invalid '{0}'. A format must be a non-empty file-" +
"extension, optionally prefixed with a '.' character.", format);
// Act and assert
@@ -70,12 +83,12 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
// Arrange
var options = new FormatterMappings();
- var expected = string.Format(@"The media type ""{0}"" is not valid. MediaTypes containing wildcards (*) " +
+ var expected = string.Format(@"The media type ""{0}"" is not valid. MediaTypes containing wildcards (*) " +
"are not allowed in formatter mappings.", format);
// Act and assert
var exception = Assert.Throws(() => options.SetMediaTypeMappingForFormat(
- "star",
+ "star",
MediaTypeHeaderValue.Parse(format)));
Assert.Equal(expected, exception.Message);
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/MediaTypeComparisonsTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/MediaTypeComparisonsTest.cs
new file mode 100644
index 0000000000..0fa93d3a2a
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/MediaTypeComparisonsTest.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.Extensions.Primitives;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Formatters
+{
+ public class MediaTypeComparisonsTest
+ {
+ [Theory]
+ [InlineData("application/json", "application/json", true)]
+ [InlineData("application/json", "application/json;charset=utf-8", true)]
+ [InlineData("application/json;charset=utf-8", "application/json", false)]
+ [InlineData("application/json;q=0.8", "application/json;q=0.9", true)]
+ [InlineData("application/json;q=0.8;charset=utf-7", "application/json;charset=utf-8;q=0.9", true)]
+ [InlineData("application/json;format=indent;charset=utf-8", "application/json", false)]
+ [InlineData("application/json", "application/json;format=indent;charset=utf-8", true)]
+ [InlineData("application/json;format=indent;charset=utf-8", "application/json;format=indent;charset=utf-8", true)]
+ [InlineData("application/json;charset=utf-8;format=indent", "application/json;format=indent;charset=utf-8", true)]
+ public void IsSubsetOf(string set, string subset, bool expectedResult)
+ {
+ // Arrange & Act
+ var result = MediaTypeComparisons.IsSubsetOf(
+ new StringSegment(set),
+ new StringSegment(subset));
+
+ // Assert
+ Assert.Equal(expectedResult, result);
+ }
+
+ [Theory]
+ [InlineData("*/*", true)]
+ [InlineData("text/*", false)]
+ [InlineData("text/plain", false)]
+ public void MatchesAllTypes(string value, bool expectedResult)
+ {
+ // Arrange
+ var mediaType = new StringSegment(value);
+
+ // Act
+ var result = MediaTypeComparisons.MatchesAllTypes(mediaType);
+
+ // Assert
+ Assert.Equal(expectedResult, result);
+ }
+
+ [Theory]
+ [InlineData("*/*", true)]
+ [InlineData("text/*", true)]
+ [InlineData("text/plain", false)]
+ public void MatchesAllSubtypes(string value, bool expectedResult)
+ {
+ // Arrange
+ var mediaType = new StringSegment(value);
+
+ // Act
+ var result = MediaTypeComparisons.MatchesAllSubtypes(mediaType);
+
+ // Assert
+ Assert.Equal(expectedResult, result);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/NoContentFormatterTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/NoContentFormatterTests.cs
index 50526d4012..e5ca0a530a 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/NoContentFormatterTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/NoContentFormatterTests.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Xunit;
@@ -41,7 +42,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
// Arrange
var type = declaredTypeAsString ? typeof(string) : typeof(object);
- var contentType = useNonNullContentType ? MediaTypeHeaderValue.Parse("text/plain") : null;
+ var contentType = useNonNullContentType ? new StringSegment("text/plain") : new StringSegment();
var context = new OutputFormatterWriteContext(
new DefaultHttpContext(),
@@ -73,7 +74,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
declaredType,
"Something non null.")
{
- ContentType = MediaTypeHeaderValue.Parse("text/plain"),
+ ContentType = new StringSegment("text/plain"),
};
var formatter = new HttpNoContentOutputFormatter();
@@ -101,7 +102,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
typeof(string),
value)
{
- ContentType = MediaTypeHeaderValue.Parse("text/plain"),
+ ContentType = new StringSegment("text/plain"),
};
var formatter = new HttpNoContentOutputFormatter()
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
index 5954a183a1..8a4aebb122 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/OutputFormatterTests.cs
@@ -7,8 +7,10 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
+using Moq.Protected;
using Xunit;
namespace Microsoft.AspNet.Mvc.Formatters
@@ -59,7 +61,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
typeof(string),
"someValue")
{
- ContentType = MediaTypeHeaderValue.Parse(httpRequest.Headers[HeaderNames.Accept]),
+ ContentType = new StringSegment(httpRequest.Headers[HeaderNames.Accept]),
};
// Act
@@ -69,17 +71,47 @@ namespace Microsoft.AspNet.Mvc.Formatters
Assert.Equal(Encoding.GetEncoding(expectedEncoding), actualEncoding);
}
+ [Theory]
+ [InlineData("application/json; charset=utf-16", "application/json; charset=utf-32")]
+ [InlineData("application/json; charset=utf-16; format=indent", "application/json; charset=utf-32; format=indent")]
+ public void WriteResponse_OverridesCharset_IfDifferentFromContentTypeCharset(
+ string contentType,
+ string expectedContentType)
+ {
+ // Arrange
+ var formatter = new Mock();
+
+ formatter
+ .Setup(f => f.SelectCharacterEncoding(It.IsAny()))
+ .Returns(Encoding.UTF32);
+
+ var formatterContext = new OutputFormatterWriteContext(
+ new DefaultHttpContext(),
+ new TestHttpResponseStreamWriterFactory().CreateWriter,
+ objectType: null,
+ @object: null)
+ {
+ ContentType = new StringSegment(contentType),
+ };
+
+ // Act
+ formatter.Object.WriteAsync(formatterContext);
+
+ // Assert
+ Assert.Equal(new StringSegment(expectedContentType), formatterContext.ContentType);
+ }
+
[Fact]
public void WriteResponseContentHeaders_NoSupportedEncodings_NoEncodingIsSet()
{
// Arrange
var formatter = new TestOutputFormatter();
- var testContentType = MediaTypeHeaderValue.Parse("text/json");
+ var testContentType = new StringSegment("text/json");
formatter.SupportedEncodings.Clear();
formatter.SupportedMediaTypes.Clear();
- formatter.SupportedMediaTypes.Add(testContentType);
+ formatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/json"));
var context = new OutputFormatterWriteContext(
new DefaultHttpContext(),
@@ -94,11 +126,11 @@ namespace Microsoft.AspNet.Mvc.Formatters
formatter.WriteResponseHeaders(context);
// Assert
- Assert.Null(context.ContentType.Encoding);
+ Assert.Null(MediaTypeHeaderValue.Parse(context.ContentType.Value).Encoding);
Assert.Equal(testContentType, context.ContentType);
// If we had set an encoding, it would be part of the content type header
- Assert.Equal(testContentType, context.HttpContext.Response.GetTypedHeaders().ContentType);
+ Assert.Equal(MediaTypeHeaderValue.Parse(testContentType.Value), context.HttpContext.Response.GetTypedHeaders().ContentType);
}
[Fact]
@@ -154,7 +186,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
formatter.SupportedTypes.Add(typeof(int));
// Act
- var contentTypes = formatter.GetSupportedContentTypes(contentType: null, objectType: typeof(string));
+ var contentTypes = formatter.GetSupportedContentTypes(
+ contentType: null,
+ objectType: typeof(string));
// Assert
Assert.Null(contentTypes);
@@ -174,7 +208,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
typeof(string),
"Hello, world!")
{
- ContentType = formatter.SupportedMediaTypes[0],
+ ContentType = new StringSegment(formatter.SupportedMediaTypes[0].ToString()),
};
// Act
@@ -194,7 +228,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xml"));
// Act
- var contentTypes = formatter.GetSupportedContentTypes(contentType: null, objectType: typeof(string));
+ var contentTypes = formatter.GetSupportedContentTypes(
+ contentType: null,
+ objectType: typeof(string));
// Assert
Assert.Equal(2, contentTypes.Count);
@@ -214,7 +250,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Act
var contentTypes = formatter.GetSupportedContentTypes(
- MediaTypeHeaderValue.Parse("application/*"),
+ "application/*",
typeof(int));
// Assert
@@ -234,7 +270,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Act
var contentTypes = formatter.GetSupportedContentTypes(
- MediaTypeHeaderValue.Parse("application/xml"),
+ "application/xml",
typeof(int));
// Assert
@@ -251,7 +287,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
formatter.SupportedMediaTypes.Clear();
// Act
- var contentTypes = formatter.GetSupportedContentTypes(contentType: null, objectType: typeof(int));
+ var contentTypes = formatter.GetSupportedContentTypes(
+ contentType: null,
+ objectType: typeof(int));
// Assert
Assert.Null(contentTypes);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StreamOutputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StreamOutputFormatterTest.cs
index 2a4598b4df..b654641c94 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StreamOutputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StreamOutputFormatterTest.cs
@@ -7,6 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Internal;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Xunit;
@@ -21,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
// Arrange
var formatter = new StreamOutputFormatter();
- var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType);
+ var contentTypeHeader = new StringSegment(contentType);
var context = new OutputFormatterWriteContext(
new DefaultHttpContext(),
@@ -46,7 +47,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
// Arrange
var formatter = new StreamOutputFormatter();
- var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType);
+ var contentTypeHeader = contentType == null ? new StringSegment() : new StringSegment(contentType);
var context = new OutputFormatterWriteContext(
new DefaultHttpContext(),
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StringOutputFormatterTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StringOutputFormatterTests.cs
index e8222d6c5d..620ac53286 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StringOutputFormatterTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/StringOutputFormatterTests.cs
@@ -7,7 +7,7 @@ using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
-using Microsoft.Net.Http.Headers;
+using Microsoft.Extensions.Primitives;
using Moq;
using Xunit;
@@ -35,9 +35,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
bool expectedCanWriteResult)
{
// Arrange
- var expectedContentType = expectedCanWriteResult ?
- MediaTypeHeaderValue.Parse("text/plain") :
- MediaTypeHeaderValue.Parse("application/json");
+ var expectedContentType = expectedCanWriteResult ?
+ new StringSegment("text/plain") :
+ new StringSegment("application/json");
var formatter = new StringOutputFormatter();
var type = useDeclaredTypeAsString ? typeof(string) : typeof(object);
@@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
new TestHttpResponseStreamWriterFactory().CreateWriter,
type,
value);
- context.ContentType = MediaTypeHeaderValue.Parse("application/json");
+ context.ContentType = new StringSegment("application/json");
// Act
var result = formatter.CanWriteResult(context);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs
index 0565b37f67..f00a048cb8 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Infrastructure/ObjectResultExecutorTest.cs
@@ -9,10 +9,12 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Formatters;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Xunit;
@@ -43,12 +45,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Act
var formatter = executor.SelectFormatter(
context,
- new[] { new MediaTypeHeaderValue("application/json") },
+ new MediaTypeCollection { "application/json" },
formatters);
// Assert
Assert.Same(formatters[1], formatter);
- Assert.Equal(new MediaTypeHeaderValue("application/json"), context.ContentType);
+ MediaTypeAssert.Equal("application/json", context.ContentType);
}
// For this test case probably the most common use case is when there is a format mapping based
@@ -72,7 +74,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Assert
Assert.IsType(executor.SelectedOutputFormatter);
- Assert.Equal("text/plain; charset=utf-8", httpContext.Response.ContentType);
+ MediaTypeAssert.Equal("text/plain; charset=utf-8", httpContext.Response.ContentType);
}
[Fact]
@@ -98,12 +100,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Act
var formatter = executor.SelectFormatter(
context,
- new[] { new MediaTypeHeaderValue("application/json") },
+ new MediaTypeCollection { "application/json" },
formatters);
// Assert
Assert.Same(formatters[1], formatter);
- Assert.Equal(new MediaTypeHeaderValue("application/json"), context.ContentType);
+ Assert.Equal(new StringSegment("application/json"), context.ContentType);
}
[Fact]
@@ -149,7 +151,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Act
var formatter = executor.SelectFormatter(
context,
- new[] { new MediaTypeHeaderValue("application/json") },
+ new MediaTypeCollection { "application/json" },
formatters);
// Assert
@@ -176,18 +178,18 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
}
// ObjectResult.ContentTypes, Accept header, expected content type
- public static TheoryData ContentTypes
+ public static TheoryData ContentTypes
{
get
{
- var contentTypes = new string[]
+ var contentTypes = new MediaTypeCollection
{
"text/plain",
"text/xml",
"application/json",
};
- return new TheoryData()
+ return new TheoryData()
{
// Empty accept header, should select based on ObjectResult.ContentTypes.
{ contentTypes, "", "application/json" },
@@ -216,7 +218,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
[Theory]
[MemberData(nameof(ContentTypes))]
public void SelectFormatter_WithMultipleProvidedContentTypes_DoesConneg(
- IEnumerable contentTypes,
+ MediaTypeCollection contentTypes,
string acceptHeader,
string expectedContentType)
{
@@ -240,12 +242,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Act
var formatter = executor.SelectFormatter(
context,
- contentTypes.Select(contentType => MediaTypeHeaderValue.Parse(contentType)).ToList(),
+ contentTypes,
formatters);
// Assert
Assert.Same(formatters[1], formatter);
- Assert.Equal(new MediaTypeHeaderValue(expectedContentType), context.ContentType);
+ Assert.Equal(new StringSegment(expectedContentType), context.ContentType);
}
[Fact]
@@ -270,12 +272,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Act
var formatter = executor.SelectFormatter(
context,
- new List(),
+ new MediaTypeCollection(),
formatters);
// Assert
Assert.Same(formatters[1], formatter);
- Assert.Equal(new MediaTypeHeaderValue("application/json"), context.ContentType);
+ Assert.Equal(new StringSegment("application/json"), context.ContentType);
Assert.Null(context.FailedContentNegotiation);
}
@@ -297,17 +299,17 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
objectType: null,
@object: null);
- context.HttpContext.Request.Headers[HeaderNames.Accept] = "text/custom, application/custom";
+ context.HttpContext.Request.Headers[HeaderNames.Accept] = "text/custom,application/custom";
// Act
var formatter = executor.SelectFormatter(
context,
- new MediaTypeHeaderValue[] { },
+ new MediaTypeCollection { },
formatters);
// Assert
Assert.Same(formatters[0], formatter);
- Assert.Equal(new MediaTypeHeaderValue("application/xml"), context.ContentType);
+ Assert.Equal(new StringSegment("application/xml"), context.ContentType);
Assert.True(context.FailedContentNegotiation);
}
@@ -373,9 +375,14 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
{
// Arrange
var result = new ObjectResult("input");
- result.ContentTypes = contentTypes
- .Select(contentType => MediaTypeHeaderValue.Parse(contentType))
- .ToList();
+
+ var mediaTypes = new MediaTypeCollection();
+ foreach (var contentType in contentTypes)
+ {
+ mediaTypes.Add(contentType);
+ }
+
+ result.ContentTypes = mediaTypes;
var executor = CreateExecutor();
@@ -395,7 +402,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Chrome & Opera
[InlineData("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "application/json; charset=utf-8")]
// IE
- [InlineData("text/html, application/xhtml+xml, */*", "application/json; charset=utf-8")]
+ [InlineData("text/html,application/xhtml+xml,*/*", "application/json; charset=utf-8")]
// Firefox & Safari
[InlineData("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "application/json; charset=utf-8")]
// Misc
@@ -432,7 +439,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
// Chrome & Opera
[InlineData("text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "application/xml; charset=utf-8")]
// IE
- [InlineData("text/html, application/xhtml+xml, */*", "application/json; charset=utf-8")]
+ [InlineData("text/html,application/xhtml+xml,*/*", "application/json; charset=utf-8")]
// Firefox & Safari
[InlineData("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "application/xml; charset=utf-8")]
// Misc
@@ -462,7 +469,8 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
await executor.ExecuteAsync(actionContext, result);
// Assert
- Assert.Equal(expectedContentType, actionContext.HttpContext.Response.Headers[HeaderNames.ContentType]);
+ var responseContentType = actionContext.HttpContext.Response.Headers[HeaderNames.ContentType];
+ MediaTypeAssert.Equal(expectedContentType, responseContentType);
}
private static IServiceCollection CreateServices()
@@ -572,7 +580,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
new public IOutputFormatter SelectFormatter(
OutputFormatterWriteContext formatterContext,
- IList contentTypes,
+ MediaTypeCollection contentTypes,
IList formatters)
{
return base.SelectFormatter(formatterContext, contentTypes, formatters);
@@ -593,7 +601,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
protected override IOutputFormatter SelectFormatter(
OutputFormatterWriteContext formatterContext,
- IList contentTypes,
+ MediaTypeCollection contentTypes,
IList formatters)
{
SelectedOutputFormatter = base.SelectFormatter(formatterContext, contentTypes, formatters);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Internal/ResponseContentTypeHelperTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Internal/ResponseContentTypeHelperTest.cs
index ebfe90f163..a7c69f3358 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Internal/ResponseContentTypeHelperTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Internal/ResponseContentTypeHelperTest.cs
@@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Text;
+using Microsoft.AspNet.Mvc.Formatters;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.Net.Http.Headers;
using Xunit;
@@ -102,13 +104,13 @@ namespace Microsoft.AspNet.Mvc.Internal
string expectedContentType)
{
// Arrange
- var defaultContentType = MediaTypeHeaderValue.Parse("text/default; p1=p1-value; charset=utf-8");
+ var defaultContentType = "text/default; p1=p1-value; charset=utf-8";
// Act
string resolvedContentType = null;
Encoding resolvedContentTypeEncoding = null;
ResponseContentTypeHelper.ResolveContentTypeAndEncoding(
- contentType,
+ contentType?.ToString(),
responseContentType,
defaultContentType,
out resolvedContentType,
@@ -123,7 +125,7 @@ namespace Microsoft.AspNet.Mvc.Internal
{
// Arrange
var expectedContentType = "invalid-content-type";
- var defaultContentType = MediaTypeHeaderValue.Parse("text/plain; charset=utf-8");
+ var defaultContentType = "text/plain; charset=utf-8";
// Act
string resolvedContentType = null;
@@ -136,6 +138,7 @@ namespace Microsoft.AspNet.Mvc.Internal
out resolvedContentTypeEncoding);
// Assert
+
Assert.Equal(expectedContentType, resolvedContentType);
Assert.Equal(Encoding.UTF8, resolvedContentTypeEncoding);
}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/MediaTypeCollectionTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/MediaTypeCollectionTest.cs
new file mode 100644
index 0000000000..663f909bd0
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/MediaTypeCollectionTest.cs
@@ -0,0 +1,61 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using Microsoft.Extensions.Primitives;
+using Microsoft.Net.Http.Headers;
+using Xunit;
+
+namespace Microsoft.AspNet.Mvc.Formatters
+{
+ public class MediaTypeCollectionTest
+ {
+ [Fact]
+ public void Add_MediaTypeHeaderValue_AddsTheStringSegmentRepresentationOfTheMediaType()
+ {
+ // Arrange
+ var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse("application/json;charset=utf-16");
+ var collection = new MediaTypeCollection();
+
+ // Act
+ collection.Add(mediaTypeHeaderValue);
+
+ // Assert
+ Assert.Contains("application/json; charset=utf-16", collection);
+ }
+
+ [Fact]
+ public void Insert_MediaTypeHeaderValue_AddsTheStringSegmentRepresentationOfTheMediaTypeOnTheGivenIndex()
+ {
+ // Arrange
+ var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse("application/json;charset=utf-16");
+ var collection = new MediaTypeCollection
+ {
+ MediaTypeHeaderValue.Parse("text/plain"),
+ MediaTypeHeaderValue.Parse("text/xml")
+ };
+
+ // Act
+ collection.Insert(1, mediaTypeHeaderValue);
+
+ // Assert
+ Assert.Equal(1, collection.IndexOf("application/json; charset=utf-16"));
+ }
+
+ [Fact]
+ public void Remove_MediaTypeHeaderValue_RemovesTheStringSegmentRepresentationOfTheMediaType()
+ {
+ // Arrange
+ var collection = new MediaTypeCollection
+ {
+ MediaTypeHeaderValue.Parse("text/plain"),
+ MediaTypeHeaderValue.Parse("text/xml")
+ };
+
+ // Act
+ collection.Remove(MediaTypeHeaderValue.Parse("text/xml"));
+
+ // Assert
+ Assert.DoesNotContain("text/xml", collection);
+ }
+ }
+}
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/PhysicalFileResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/PhysicalFileResultTest.cs
index 00884f2eb3..b18039feb4 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/PhysicalFileResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/PhysicalFileResultTest.cs
@@ -10,11 +10,11 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
-using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -41,14 +41,14 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var path = Path.GetFullPath("helllo.txt");
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
- var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
+ var expectedMediaType = contentType;
// Act
var result = new PhysicalFileResult(path, contentType);
// Assert
Assert.Equal(path, result.FileName);
- Assert.Equal(expectedMediaType, result.ContentType);
+ MediaTypeAssert.Equal(expectedMediaType, result.ContentType);
}
[Fact]
@@ -99,7 +99,7 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var expectedContentType = "text/foo; charset=us-ascii";
var path = Path.GetFullPath(Path.Combine(".", "TestFiles", "FilePathResultTestFile_ASCII.txt"));
- var result = new TestPhysicalFileResult(path, MediaTypeHeaderValue.Parse(expectedContentType))
+ var result = new TestPhysicalFileResult(path, expectedContentType)
{
IsAscii = true
};
@@ -205,11 +205,6 @@ namespace Microsoft.AspNet.Mvc
{
}
- public TestPhysicalFileResult(string filePath, MediaTypeHeaderValue contentType)
- : base(filePath, contentType)
- {
- }
-
public bool IsAscii { get; set; } = false;
protected override Stream GetFileStream(string path)
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ProducesAttributeTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ProducesAttributeTests.cs
index d70fa2cae1..535e16d186 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ProducesAttributeTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ProducesAttributeTests.cs
@@ -8,7 +8,9 @@ using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.Formatters;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Routing;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -21,8 +23,8 @@ namespace Microsoft.AspNet.Mvc.Test
public async Task ProducesAttribute_SetsContentType()
{
// Arrange
- var mediaType1 = MediaTypeHeaderValue.Parse("application/json");
- var mediaType2 = MediaTypeHeaderValue.Parse("text/json;charset=utf-8");
+ var mediaType1 = new StringSegment("application/json");
+ var mediaType2 = new StringSegment("text/json;charset=utf-8");
var producesContentAttribute = new ProducesAttribute("application/json", "text/json;charset=utf-8");
var resultExecutingContext = CreateResultExecutingContext(new IFilterMetadata[] { producesContentAttribute });
var next = new ResultExecutionDelegate(
@@ -34,8 +36,8 @@ namespace Microsoft.AspNet.Mvc.Test
// Assert
var objectResult = resultExecutingContext.Result as ObjectResult;
Assert.Equal(2, objectResult.ContentTypes.Count);
- ValidateMediaType(mediaType1, objectResult.ContentTypes[0]);
- ValidateMediaType(mediaType2, objectResult.ContentTypes[1]);
+ MediaTypeAssert.Equal(mediaType1, objectResult.ContentTypes[0]);
+ MediaTypeAssert.Equal(mediaType2, objectResult.ContentTypes[1]);
}
[Fact]
@@ -153,20 +155,6 @@ namespace Microsoft.AspNet.Mvc.Test
Assert.Empty(producesAttribute.ContentTypes);
}
- private static void ValidateMediaType(MediaTypeHeaderValue expectedMediaType, MediaTypeHeaderValue actualMediaType)
- {
- Assert.Equal(expectedMediaType.MediaType, actualMediaType.MediaType);
- Assert.Equal(expectedMediaType.SubType, actualMediaType.SubType);
- Assert.Equal(expectedMediaType.Charset, actualMediaType.Charset);
- Assert.Equal(expectedMediaType.MatchesAllTypes, actualMediaType.MatchesAllTypes);
- Assert.Equal(expectedMediaType.MatchesAllSubTypes, actualMediaType.MatchesAllSubTypes);
- Assert.Equal(expectedMediaType.Parameters.Count, actualMediaType.Parameters.Count);
- foreach (var item in expectedMediaType.Parameters)
- {
- Assert.Equal(item.Value, NameValueHeaderValue.Find(actualMediaType.Parameters, item.Name).Value);
- }
- }
-
private static ResultExecutedContext CreateResultExecutedContext(ResultExecutingContext context)
{
return new ResultExecutedContext(context, context.Filters, context.Result, context.Controller);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/VirtualFileResultTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/VirtualFileResultTest.cs
index 3d6c5e3a4c..28a12761e3 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/VirtualFileResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/VirtualFileResultTest.cs
@@ -11,11 +11,11 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
-using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -42,14 +42,14 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var path = Path.GetFullPath("helllo.txt");
var contentType = "text/plain; charset=us-ascii; p1=p1-value";
- var expectedMediaType = MediaTypeHeaderValue.Parse(contentType);
+ var expectedMediaType = contentType;
// Act
var result = new VirtualFileResult(path, contentType);
// Assert
Assert.Equal(path, result.FileName);
- Assert.Equal(expectedMediaType, result.ContentType);
+ MediaTypeAssert.Equal(expectedMediaType, result.ContentType);
}
[Fact]
@@ -137,7 +137,7 @@ namespace Microsoft.AspNet.Mvc
// Arrange
var expectedContentType = "text/foo; charset=us-ascii";
var result = new TestVirtualFileResult(
- "FilePathResultTestFile_ASCII.txt", MediaTypeHeaderValue.Parse(expectedContentType))
+ "FilePathResultTestFile_ASCII.txt", expectedContentType)
{
FileProvider = GetFileProvider("FilePathResultTestFile_ASCII.txt"),
IsAscii = true,
@@ -347,11 +347,6 @@ namespace Microsoft.AspNet.Mvc
{
}
- public TestVirtualFileResult(string filePath, MediaTypeHeaderValue contentType)
- : base(filePath, contentType)
- {
- }
-
public bool IsAscii { get; set; } = false;
protected override Stream GetFileStream(IFileInfo fileInfo)
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/Infrastructure/JsonResultExecutorTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/Infrastructure/JsonResultExecutorTest.cs
index fbd79009ce..92cb8c551d 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/Infrastructure/JsonResultExecutorTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/Infrastructure/JsonResultExecutorTest.cs
@@ -50,7 +50,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
var context = GetActionContext();
var result = new JsonResult(new { foo = "abcd" });
- result.ContentType = new MediaTypeHeaderValue("text/json");
+ result.ContentType = "text/json";
var executor = CreateExcutor();
// Act
@@ -74,7 +74,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
result.ContentType = new MediaTypeHeaderValue("text/json")
{
Encoding = Encoding.ASCII
- };
+ }.ToString();
var executor = CreateExcutor();
// Act
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs
index de891c2af5..f5f96cf73c 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonOutputFormatterTests.cs
@@ -14,6 +14,7 @@ using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Testing;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Newtonsoft.Json;
@@ -262,7 +263,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
typeof(string),
content)
{
- ContentType = mediaType,
+ ContentType = new StringSegment(mediaType.ToString()),
};
// Act
@@ -313,7 +314,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
outputType,
outputValue)
{
- ContentType = mediaTypeHeaderValue,
+ ContentType = new StringSegment(contentType),
};
}
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerOutputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerOutputFormatterTest.cs
index 7bcf82d570..294ae93152 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerOutputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerOutputFormatterTest.cs
@@ -12,6 +12,7 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Formatters.Xml.Internal;
using Microsoft.AspNet.Testing.xunit;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -123,7 +124,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var formatter = new TestXmlDataContractSerializerOutputFormatter();
var context = GetOutputFormatterContext(input, typeof(DummyClass));
- context.ContentType = MediaTypeHeaderValue.Parse("application/xml");
+ context.ContentType = new StringSegment("application/xml");
// Act
formatter.CanWriteResult(context);
@@ -382,7 +383,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
// Arrange
var formatter = new XmlDataContractSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(input, declaredType);
- outputFormatterContext.ContentType = MediaTypeHeaderValue.Parse("application/xml");
+ outputFormatterContext.ContentType = new StringSegment("application/xml");
// Act
var result = formatter.CanWriteResult(outputFormatterContext);
@@ -412,7 +413,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
// Act
var result = formatter.GetSupportedContentTypes(
- MediaTypeHeaderValue.Parse("application/xml"),
+ "application/xml",
type);
// Assert
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerOutputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerOutputFormatterTest.cs
index 8aec54e7e3..b876b565d8 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerOutputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerOutputFormatterTest.cs
@@ -11,6 +11,7 @@ using System.Xml.Serialization;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Formatters.Xml.Internal;
+using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
using Moq;
using Xunit;
@@ -76,7 +77,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var formatter = new TestXmlSerializerOutputFormatter();
var context = GetOutputFormatterContext(input, typeof(DummyClass));
- context.ContentType = MediaTypeHeaderValue.Parse("application/xml");
+ context.ContentType = new StringSegment("application/xml");
// Act
formatter.CanWriteResult(context);
@@ -300,7 +301,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
// Arrange
var formatter = new XmlSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(input, declaredType);
- outputFormatterContext.ContentType = MediaTypeHeaderValue.Parse("application/xml");
+ outputFormatterContext.ContentType = new StringSegment("application/xml");
// Act
var result = formatter.CanWriteResult(outputFormatterContext);
@@ -342,7 +343,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var formatter = new XmlSerializerOutputFormatter();
// Act
- var result = formatter.GetSupportedContentTypes(MediaTypeHeaderValue.Parse("application/xml"), type);
+ var result = formatter.GetSupportedContentTypes("application/xml", type);
// Assert
if (expectedOutput != null)
diff --git a/test/Microsoft.AspNet.Mvc.TestCommon/MediaTypeAssert.cs b/test/Microsoft.AspNet.Mvc.TestCommon/MediaTypeAssert.cs
new file mode 100644
index 0000000000..e44bc0179b
--- /dev/null
+++ b/test/Microsoft.AspNet.Mvc.TestCommon/MediaTypeAssert.cs
@@ -0,0 +1,47 @@
+using System;
+using Microsoft.Extensions.Primitives;
+using Microsoft.Net.Http.Headers;
+using Xunit.Sdk;
+
+namespace Microsoft.AspNet.Mvc.TestCommon
+{
+ public class MediaTypeAssert
+ {
+ public static void Equal(string left, string right)
+ {
+ Equal(new StringSegment(left), new StringSegment(right));
+ }
+
+ public static void Equal(string left, StringSegment right)
+ {
+ Equal(new StringSegment(left), right);
+ }
+
+ public static void Equal(StringSegment left, string right)
+ {
+ Equal(left, new StringSegment(right));
+ }
+
+ public static void Equal(StringSegment left, StringSegment right)
+ {
+ if (!left.HasValue && !right.HasValue)
+ {
+ return;
+ }
+ else if (!left.HasValue || !right.HasValue)
+ {
+ throw new EqualException(left.ToString(), right.ToString());
+ }
+
+ MediaTypeHeaderValue leftMediaType = null;
+ MediaTypeHeaderValue rightMediaType = null;
+
+ if (!MediaTypeHeaderValue.TryParse(left.Value, out leftMediaType) ||
+ !MediaTypeHeaderValue.TryParse(right.Value, out rightMediaType) ||
+ !leftMediaType.Equals(rightMediaType))
+ {
+ throw new EqualException(left.ToString(), right.ToString());
+ }
+ }
+ }
+}
diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs
index 1c56d6055f..977c997a5e 100644
--- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs
+++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ControllerUnitTestabilityTests.cs
@@ -8,6 +8,7 @@ using System.Text;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Controllers;
+using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Routing;
using Moq;
using Newtonsoft.Json;
@@ -90,7 +91,7 @@ namespace Microsoft.AspNet.Mvc
var contentResult = Assert.IsType(result);
Assert.Equal(content, contentResult.Content);
Assert.Equal("text/asp; charset=us-ascii", contentResult.ContentType.ToString());
- Assert.Equal(encoding, contentResult.ContentType.Encoding);
+ Assert.Equal(encoding, MediaTypeEncoding.GetEncoding(contentResult.ContentType));
}
[Theory]
diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs
index 93abe8738f..96a9ff892f 100644
--- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewComponentResultTest.cs
@@ -12,9 +12,11 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.Infrastructure;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Mvc.ViewComponents;
using Microsoft.AspNet.Mvc.ViewFeatures;
using Microsoft.AspNet.Mvc.ViewFeatures.Buffer;
@@ -367,26 +369,26 @@ namespace Microsoft.AspNet.Mvc
Assert.Equal(404, actionContext.HttpContext.Response.StatusCode);
}
- public static TheoryData ViewComponentResultContentTypeData
+ public static TheoryData ViewComponentResultContentTypeData
{
get
{
- return new TheoryData
+ return new TheoryData
{
{
null,
"text/html; charset=utf-8"
},
{
- new MediaTypeHeaderValue("text/foo"),
+ "text/foo",
"text/foo"
},
{
- MediaTypeHeaderValue.Parse("text/foo;p1=p1-value"),
+ "text/foo;p1=p1-value",
"text/foo; p1=p1-value"
},
{
- new MediaTypeHeaderValue("text/foo") { Encoding = Encoding.ASCII },
+ new MediaTypeHeaderValue("text/foo") { Encoding = Encoding.ASCII }.ToString(),
"text/foo; charset=us-ascii"
}
};
@@ -396,8 +398,8 @@ namespace Microsoft.AspNet.Mvc
[Theory]
[MemberData(nameof(ViewComponentResultContentTypeData))]
public async Task ViewComponentResult_SetsContentTypeHeader(
- MediaTypeHeaderValue contentType,
- string expectedContentTypeHeaderValue)
+ string contentType,
+ string expectedContentType)
{
// Arrange
var descriptor = new ViewComponentDescriptor()
@@ -424,13 +426,14 @@ namespace Microsoft.AspNet.Mvc
await viewComponentResult.ExecuteResultAsync(actionContext);
// Assert
- Assert.Equal(expectedContentTypeHeaderValue, actionContext.HttpContext.Response.ContentType);
+ var resultContentType = actionContext.HttpContext.Response.ContentType;
+ MediaTypeAssert.Equal(expectedContentType, resultContentType);
// Check if the original instance provided by the user has not changed.
// Since we do not have access to the new instance created within the view executor,
// check if at least the content is the same.
var contentTypeAfterViewResultExecution = contentType?.ToString();
- Assert.Equal(contentTypeBeforeViewResultExecution, contentTypeAfterViewResultExecution);
+ MediaTypeAssert.Equal(contentTypeBeforeViewResultExecution, contentTypeAfterViewResultExecution);
}
[Fact]
@@ -454,7 +457,7 @@ namespace Microsoft.AspNet.Mvc
{
Arguments = new { name = "World!" },
ViewComponentName = "Text",
- ContentType = new MediaTypeHeaderValue("text/html") { Encoding = Encoding.UTF8 },
+ ContentType = new MediaTypeHeaderValue("text/html") { Encoding = Encoding.UTF8 }.ToString(),
TempData = _tempDataDictionary,
};
diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/PartialViewResultExecutorTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/PartialViewResultExecutorTest.cs
index d88a768cd1..a07a8cfe7a 100644
--- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/PartialViewResultExecutorTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/PartialViewResultExecutorTest.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Routing;
@@ -262,7 +263,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
var context = GetActionContext();
var executor = GetViewExecutor();
- var contentType = MediaTypeHeaderValue.Parse("application/x-my-content-type");
+ var contentType = "application/x-my-content-type";
var viewResult = new PartialViewResult
{
@@ -281,7 +282,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
// Check if the original instance provided by the user has not changed.
// Since we do not have access to the new instance created within the view executor,
// check if at least the content is the same.
- Assert.Null(contentType.Encoding);
+ Assert.Null(MediaTypeEncoding.GetEncoding(contentType));
}
[Fact]
diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewExecutorTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewExecutorTest.cs
index b7a09d8e4a..a6c5c47baf 100644
--- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewExecutorTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewExecutorTest.cs
@@ -10,8 +10,10 @@ using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
+using Microsoft.AspNet.Mvc.TestCommon;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Routing;
using Microsoft.Extensions.DependencyInjection;
@@ -115,11 +117,11 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
view,
viewData,
Mock.Of(),
- contentType,
+ contentType?.ToString(),
statusCode: null);
// Assert
- Assert.Equal(expectedContentType, context.Response.ContentType);
+ MediaTypeAssert.Equal(expectedContentType, context.Response.ContentType);
Assert.Equal("abcd", Encoding.UTF8.GetString(memoryStream.ToArray()));
}
diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewResultExecutorTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewResultExecutorTest.cs
index 63b0242203..8b0ff03888 100644
--- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewResultExecutorTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ViewFeatures/ViewResultExecutorTest.cs
@@ -6,6 +6,7 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc.Abstractions;
+using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.ViewEngines;
using Microsoft.AspNet.Routing;
@@ -258,7 +259,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
var context = GetActionContext();
var executor = GetViewExecutor();
- var contentType = MediaTypeHeaderValue.Parse("application/x-my-content-type");
+ var contentType = "application/x-my-content-type";
var viewResult = new ViewResult
{
@@ -273,11 +274,6 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
// Assert
Assert.Equal("application/x-my-content-type", context.HttpContext.Response.ContentType);
-
- // Check if the original instance provided by the user has not changed.
- // Since we do not have access to the new instance created within the view executor,
- // check if at least the content is the same.
- Assert.Null(contentType.Encoding);
}
[Fact]
diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs
index c2fe8834f1..f5aa58af41 100644
--- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs
+++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/ApiControllerTest.cs
@@ -10,6 +10,7 @@ using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Internal;
using Microsoft.AspNet.Mvc;
using Microsoft.AspNet.Mvc.Controllers;
+using Microsoft.AspNet.Mvc.Formatters;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Routing;
using Newtonsoft.Json;
@@ -264,7 +265,7 @@ namespace System.Web.Http
var jsonResult = Assert.IsType(result);
Assert.Same(product, jsonResult.Value);
- Assert.Same(Encoding.UTF8, jsonResult.ContentType.Encoding);
+ Assert.Same(Encoding.UTF8, MediaTypeEncoding.GetEncoding(jsonResult.ContentType));
}
[Fact]
diff --git a/test/WebSites/BasicWebSite/Controllers/JsonResultController.cs b/test/WebSites/BasicWebSite/Controllers/JsonResultController.cs
index 24b341b12d..1b7f3311de 100644
--- a/test/WebSites/BasicWebSite/Controllers/JsonResultController.cs
+++ b/test/WebSites/BasicWebSite/Controllers/JsonResultController.cs
@@ -20,7 +20,7 @@ namespace BasicWebSite.Controllers
public JsonResult CustomContentType()
{
var result = new JsonResult(new { Message = "hello" });
- result.ContentType = MediaTypeHeaderValue.Parse("application/message+json");
+ result.ContentType = "application/message+json";
return result;
}
diff --git a/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs b/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs
index 326d32d064..4a1225efbe 100644
--- a/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs
+++ b/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V3.cs
@@ -38,9 +38,11 @@ namespace BasicWebSite.Formatters
builder.AppendLine();
builder.AppendLine("END:VCARD");
+ var selectedEncoding = MediaTypeEncoding.GetEncoding(context.ContentType) ?? Encoding.UTF8;
+
await context.HttpContext.Response.WriteAsync(
builder.ToString(),
- context.ContentType?.Encoding ?? Encoding.UTF8);
+ selectedEncoding);
}
}
}
\ No newline at end of file
diff --git a/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs b/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs
index ffcc5e2913..875c695db6 100644
--- a/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs
+++ b/test/WebSites/BasicWebSite/Formatters/VCardFormatter_V4.cs
@@ -41,9 +41,11 @@ namespace BasicWebSite.Formatters
builder.AppendLine();
builder.AppendLine("END:VCARD");
+ var selectedEncoding = MediaTypeEncoding.GetEncoding(context.ContentType) ?? Encoding.UTF8;
+
await context.HttpContext.Response.WriteAsync(
builder.ToString(),
- context.ContentType?.Encoding ?? Encoding.UTF8);
+ selectedEncoding);
}
}
}
\ No newline at end of file
diff --git a/test/WebSites/FiltersWebSite/Filters/RandomNumberFilter.cs b/test/WebSites/FiltersWebSite/Filters/RandomNumberFilter.cs
index 4cd83cbfa7..ca52a63b55 100644
--- a/test/WebSites/FiltersWebSite/Filters/RandomNumberFilter.cs
+++ b/test/WebSites/FiltersWebSite/Filters/RandomNumberFilter.cs
@@ -14,7 +14,7 @@ namespace FiltersWebSite
context.Result = new ContentResult()
{
Content = "4",
- ContentType = new MediaTypeHeaderValue("text/plain")
+ ContentType = "text/plain"
};
}
diff --git a/test/WebSites/FiltersWebSite/Filters/ShortCircuitActionFilter.cs b/test/WebSites/FiltersWebSite/Filters/ShortCircuitActionFilter.cs
index 54a27638e8..dbc2891f79 100644
--- a/test/WebSites/FiltersWebSite/Filters/ShortCircuitActionFilter.cs
+++ b/test/WebSites/FiltersWebSite/Filters/ShortCircuitActionFilter.cs
@@ -14,7 +14,7 @@ namespace FiltersWebSite
context.Result = new ContentResult
{
Content = "The Action was never executed",
- ContentType = new MediaTypeHeaderValue("text/plain")
+ ContentType = "text/plain"
};
}
}
diff --git a/test/WebSites/FiltersWebSite/Helper/Helpers.cs b/test/WebSites/FiltersWebSite/Helper/Helpers.cs
index 897d5088f2..99a8fd830d 100644
--- a/test/WebSites/FiltersWebSite/Helper/Helpers.cs
+++ b/test/WebSites/FiltersWebSite/Helper/Helpers.cs
@@ -21,7 +21,7 @@ namespace FiltersWebSite
return new ContentResult()
{
Content = content,
- ContentType = new MediaTypeHeaderValue("text/plain"),
+ ContentType = "text/plain",
};
}
}