Remove runtime dependency usage of MediaTypeHeaderValue.
Removes usage of MediaTypeHeaderValue in ApiExplorer, InputFormatters and OutputFormatters Public interface changes with stub implementation.
This commit is contained in:
parent
32d15186a0
commit
830fd410f5
|
|
@ -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
|
||||
/// <see cref="IOutputFormatter.WriteAsync(OutputFormatterWriteContext)"/>
|
||||
/// </remarks>
|
||||
public virtual MediaTypeHeaderValue ContentType { get; set; }
|
||||
public virtual StringSegment ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating that content-negotiation could not find a formatter based on the
|
||||
|
|
|
|||
|
|
@ -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
|
|||
/// <summary>
|
||||
/// The media type of the response.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue MediaType { get; set; }
|
||||
public string MediaType { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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<MediaTypeHeaderValue>();
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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 <see cref="Type"/> for which the supported content types are desired.
|
||||
/// </param>
|
||||
/// <returns>Content types which are supported by the <see cref="Formatters.IOutputFormatter"/>.</returns>
|
||||
IReadOnlyList<MediaTypeHeaderValue> GetSupportedContentTypes(
|
||||
MediaTypeHeaderValue contentType,
|
||||
IReadOnlyList<string> GetSupportedContentTypes(
|
||||
string contentType,
|
||||
Type objectType);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|||
/// <summary>
|
||||
/// Configures a collection of allowed content types which can be produced by the action.
|
||||
/// </summary>
|
||||
void SetContentTypes(IList<MediaTypeHeaderValue> contentTypes);
|
||||
void SetContentTypes(MediaTypeCollection contentTypes);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IList<MediaTypeHeaderValue> ContentTypes { get; set; }
|
||||
public MediaTypeCollection ContentTypes { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
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<MediaTypeHeaderValue> GetContentTypes(string firstArg, string[] args)
|
||||
private MediaTypeCollection GetContentTypes(string firstArg, string[] args)
|
||||
{
|
||||
var completeArgs = new List<string>();
|
||||
completeArgs.Add(firstArg);
|
||||
completeArgs.AddRange(args);
|
||||
var contentTypes = new List<MediaTypeHeaderValue>();
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set the content representing the body of the response.
|
||||
|
|
@ -27,9 +27,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
public string Content { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
|
||||
/// Gets or sets the Content-Type header for the response.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue ContentType { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the HTTP status code.
|
||||
|
|
|
|||
|
|
@ -271,7 +271,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
var result = new ContentResult
|
||||
{
|
||||
Content = content,
|
||||
ContentType = contentType
|
||||
ContentType = contentType?.ToString()
|
||||
};
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -31,10 +31,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
throw new ArgumentNullException(nameof(fileContents));
|
||||
}
|
||||
if (contentType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contentType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -45,18 +41,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <param name="fileContents">The bytes that represent the file contents.</param>
|
||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <paramref name="contentType"/>.
|
||||
/// </summary>
|
||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||
protected FileResult(MediaTypeHeaderValue contentType)
|
||||
protected FileResult(string contentType)
|
||||
{
|
||||
if (contentType == null)
|
||||
{
|
||||
|
|
@ -35,9 +36,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
|
||||
/// Gets the Content-Type header for the response.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue ContentType { get; }
|
||||
public string ContentType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file name that will be used in the Content-Disposition header of the response.
|
||||
|
|
|
|||
|
|
@ -42,18 +42,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <param name="fileStream">The stream with the file.</param>
|
||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<IApiResponseMetadataProvider>();
|
||||
var supportedMediaTypes = new List<MediaTypeHeaderValue>();
|
||||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to specify mapping between the URL Format and corresponding <see cref="MediaTypeHeaderValue"/>.
|
||||
/// Used to specify mapping between the URL Format and corresponding media type.
|
||||
/// </summary>
|
||||
public class FormatterMappings
|
||||
{
|
||||
private readonly Dictionary<string, MediaTypeHeaderValue> _map =
|
||||
new Dictionary<string, MediaTypeHeaderValue>(StringComparer.OrdinalIgnoreCase);
|
||||
private readonly Dictionary<string, string> _map =
|
||||
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Sets mapping for the format to specified <see cref="MediaTypeHeaderValue"/>.
|
||||
/// If the format already exists, the <see cref="MediaTypeHeaderValue"/> 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.
|
||||
/// </summary>
|
||||
/// <param name="format">The format value.</param>
|
||||
/// <param name="contentType">The <see cref="MediaTypeHeaderValue"/> for the format value.</param>
|
||||
/// <param name="contentType">The media type for the format value.</param>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets mapping for the format to specified media type.
|
||||
/// If the format already exists, the media type will be overwritten with the new value.
|
||||
/// </summary>
|
||||
/// <param name="format">The format value.</param>
|
||||
/// <param name="contentType">The media type for the format value.</param>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets <see cref="MediaTypeHeaderValue"/> for the specified format.
|
||||
/// Gets the media type for the specified format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format value.</param>
|
||||
/// <returns>The <see cref="MediaTypeHeaderValue"/> for input format.</returns>
|
||||
public MediaTypeHeaderValue GetMediaTypeMappingForFormat(string format)
|
||||
/// <returns>The media type for input format.</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the <see cref="MediaTypeHeaderValue"/> mapping for the format.
|
||||
/// Clears the media type mapping for the format.
|
||||
/// </summary>
|
||||
/// <param name="format">The format value.</param>
|
||||
/// <returns><c>true</c> if the format is successfully found and cleared; otherwise, <c>false</c>.</returns>
|
||||
|
|
|
|||
|
|
@ -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<Encoding> SupportedEncodings { get; } = new List<Encoding>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mutable collection of <see cref="MediaTypeHeaderValue"/> elements supported by
|
||||
/// Gets the mutable collection of media type elements supported by
|
||||
/// this <see cref="InputFormatter"/>.
|
||||
/// </summary>
|
||||
public IList<MediaTypeHeaderValue> SupportedMediaTypes { get; } = new List<MediaTypeHeaderValue>();
|
||||
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
|
|||
|
||||
/// <summary>
|
||||
/// Returns an <see cref="Encoding"/> based on <paramref name="context"/>'s
|
||||
/// <see cref="MediaTypeHeaderValue.Charset"/>.
|
||||
/// character set.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="InputFormatterContext"/>.</param>
|
||||
/// <returns>
|
||||
/// An <see cref="Encoding"/> based on <paramref name="context"/>'s
|
||||
/// <see cref="MediaTypeHeaderValue.Charset"/>. <c>null</c> if no supported encoding was found.
|
||||
/// character set. <c>null</c> if no supported encoding was found.
|
||||
/// </returns>
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A collection of media types.
|
||||
/// </summary>
|
||||
public class MediaTypeCollection : Collection<string>
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="MediaTypeCollection"/>.
|
||||
/// </summary>
|
||||
public MediaTypeCollection()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an object to the end of the <see cref="MediaTypeCollection"/>.
|
||||
/// </summary>
|
||||
/// <param name="item">The media type to be added to the end of the <see cref="MediaTypeCollection"/>.</param>
|
||||
public void Add(MediaTypeHeaderValue item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
Add(item.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an element into the <see cref="MediaTypeCollection"/> at the specified index.
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
|
||||
/// <param name="item">The media type to insert.</param>
|
||||
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());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the first occurrence of a specific media type from the <see cref="MediaTypeCollection"/>.
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns><code>true</code> if <paramref name="item"/> is successfully removed; otherwise, <code>false</code>.
|
||||
/// This method also returns <code>false</code> if <paramref name="item"/> was not found in the original
|
||||
/// <see cref="MediaTypeCollection"/>.</returns>
|
||||
public bool Remove(MediaTypeHeaderValue item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(item));
|
||||
}
|
||||
|
||||
return Remove(item.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Different types of tests against media type values.
|
||||
/// </summary>
|
||||
public static class MediaTypeComparisons
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if the <paramref name="subset" /> media type is a subset of the <paramref name="set" /> media type
|
||||
/// without taking into account the quality parameter.
|
||||
/// </summary>
|
||||
/// <param name="set">The more general media type.</param>
|
||||
/// <param name="subset">The more specific media type.</param>
|
||||
/// <returns><code>true</code> if <paramref name="set" /> is a more general media type than <paramref name="subset"/>;
|
||||
/// otherwise <code>false</code>.</returns>
|
||||
public static bool IsSubsetOf(StringSegment set, string subset)
|
||||
{
|
||||
return IsSubsetOf(set, new StringSegment(subset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the <paramref name="subset" /> media type is a subset of the <paramref name="set" /> media type
|
||||
/// without taking into account the quality parameter.
|
||||
/// </summary>
|
||||
/// <param name="set">The more general media type.</param>
|
||||
/// <param name="subset">The more specific media type.</param>
|
||||
/// <returns><code>true</code> if <paramref name="set" /> is a more general media type than <paramref name="subset"/>;
|
||||
/// otherwise <code>false</code>.</returns>
|
||||
public static bool IsSubsetOf(string set, string subset)
|
||||
{
|
||||
return IsSubsetOf(new StringSegment(set), new StringSegment(subset));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the <paramref name="subset" /> media type is a subset of the <paramref name="set" /> media type.
|
||||
/// Two media types are compatible if one is a subset of the other ignoring any charset
|
||||
/// parameter.
|
||||
/// </summary>
|
||||
/// <param name="set">The more general media type.</param>
|
||||
/// <param name="subset">The more specific media type.</param>
|
||||
/// <param name="ignoreQuality">Whether or not we should skip checking the quality parameter.</param>
|
||||
/// <returns><code>true</code> if <paramref name="set" /> is a more general media type than <paramref name="subset"/>;
|
||||
/// otherwise <code>false</code>.</returns>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the type of a given <paramref name="mediaType" /> matches all types, E.g, */*.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type to check</param>
|
||||
/// <returns><code>true</code> if the <paramref name="mediaType" /> matches all subtypes; otherwise <code>false</code>.</returns>
|
||||
public static bool MatchesAllTypes(string mediaType)
|
||||
{
|
||||
return MatchesAllTypes(new StringSegment(mediaType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the type of a given <paramref name="mediaType" /> matches all types, E.g, */*.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type to check</param>
|
||||
/// <returns><code>true</code> if the <paramref name="mediaType" /> matches all subtypes; otherwise <code>false</code>.</returns>
|
||||
public static bool MatchesAllTypes(StringSegment mediaType)
|
||||
{
|
||||
if (!mediaType.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MediaTypeHeaderValue parsedMediaType;
|
||||
return MediaTypeHeaderValue.TryParse(mediaType.Value, out parsedMediaType) &&
|
||||
parsedMediaType.MatchesAllTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given <paramref name="mediaType" /> matches all subtypes, E.g, text/*.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type to check</param>
|
||||
/// <returns><code>true</code> if the <paramref name="mediaType" /> matches all subtypes; otherwise <code>false</code>.</returns>
|
||||
public static bool MatchesAllSubtypes(string mediaType)
|
||||
{
|
||||
return MatchesAllSubtypes(new StringSegment(mediaType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the given <paramref name="mediaType" /> matches all subtypes, E.g, text/*.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type to check</param>
|
||||
/// <returns><code>true</code> if the <paramref name="mediaType" /> matches all subtypes; otherwise <code>false</code>.</returns>
|
||||
public static bool MatchesAllSubtypes(StringSegment mediaType)
|
||||
{
|
||||
if (!mediaType.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MediaTypeHeaderValue parsedMediaType;
|
||||
return MediaTypeHeaderValue.TryParse(mediaType.Value, out parsedMediaType) &&
|
||||
parsedMediaType.MatchesAllSubTypes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
/// <summary>
|
||||
/// A set of operations to manipulate the encoding of a media type value.
|
||||
/// </summary>
|
||||
public class MediaTypeEncoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Encoding"/> for the given <see cref="mediaType"/> if it exists.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type from which to get the charset parameter.</param>
|
||||
/// <returns>The <see cref="Encoding"/> of the media type if it exists; otherwise <code>null</code>.</returns>
|
||||
public static Encoding GetEncoding(StringSegment mediaType)
|
||||
{
|
||||
var charset = GetCharsetParameter(mediaType);
|
||||
return GetEncodingFromCharset(charset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Encoding"/> for the given <see cref="mediaType"/> if it exists.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type from which to get the charset parameter.</param>
|
||||
/// <returns>The <see cref="Encoding"/> of the media type if it exists or a <see cref="StringSegment"/> without value if not.</returns>
|
||||
public static Encoding GetEncoding(string mediaType)
|
||||
{
|
||||
var charset = GetCharsetParameter(new StringSegment(mediaType));
|
||||
return GetEncodingFromCharset(charset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the charset parameter of the given <paramref name="mediaType"/> if it exists.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type from which to get the charset parameter.</param>
|
||||
/// <returns>The charset of the media type if it exists or a <see cref="StringSegment"/> without value if not.</returns>
|
||||
public static StringSegment GetCharsetParameter(StringSegment mediaType)
|
||||
{
|
||||
MediaTypeHeaderValue parsedMediaType;
|
||||
if (MediaTypeHeaderValue.TryParse(mediaType.Value, out parsedMediaType))
|
||||
{
|
||||
return new StringSegment(parsedMediaType.Charset);
|
||||
}
|
||||
return new StringSegment();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the encoding of the given <paramref name="mediaType"/> with the provided
|
||||
/// <paramref name="encoding"/>.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type whose encoding will be replaced.</param>
|
||||
/// <param name="encoding">The encoding that will replace the encoding in the <paramref name="mediaType"/></param>
|
||||
/// <returns>A media type with the replaced encoding.</returns>
|
||||
public static string ReplaceEncoding(string mediaType, Encoding encoding)
|
||||
{
|
||||
return ReplaceEncoding(new StringSegment(mediaType), encoding);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the encoding of the given <paramref name="mediaType"/> with the provided
|
||||
/// <paramref name="encoding"/>.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The media type whose encoding will be replaced.</param>
|
||||
/// <param name="encoding">The encoding that will replace the encoding in the <paramref name="mediaType"/></param>
|
||||
/// <returns>A media type with the replaced encoding.</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// A media type with its associated quality.
|
||||
/// </summary>
|
||||
public struct MediaTypeSegmentWithQuality
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes an instance of <see cref="MediaTypeSegmentWithQuality"/>.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The <see cref="StringSegment"/> containing the media type.</param>
|
||||
/// <param name="quality">The quality parameter of the media type or 1 in the case it does not exist.</param>
|
||||
public MediaTypeSegmentWithQuality(StringSegment mediaType, double quality)
|
||||
{
|
||||
MediaType = mediaType;
|
||||
Quality = quality;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the media type of this <see cref="MediaTypeSegmentWithQuality"/>.
|
||||
/// </summary>
|
||||
public StringSegment MediaType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the quality of this <see cref="MediaTypeSegmentWithQuality"/>.
|
||||
/// </summary>
|
||||
public double Quality { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString()
|
||||
{
|
||||
// For logging purposes
|
||||
return MediaType.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|||
/// </summary>
|
||||
public abstract class OutputFormatter : IOutputFormatter, IApiResponseFormatMetadataProvider
|
||||
{
|
||||
// using a field so we can return it as both IList and IReadOnlyList
|
||||
private readonly List<MediaTypeHeaderValue> _supportedMediaTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OutputFormatter"/> class.
|
||||
/// </summary>
|
||||
protected OutputFormatter()
|
||||
{
|
||||
SupportedEncodings = new List<Encoding>();
|
||||
_supportedMediaTypes = new List<MediaTypeHeaderValue>();
|
||||
SupportedMediaTypes = new MediaTypeCollection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -37,13 +35,10 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
public IList<Encoding> SupportedEncodings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mutable collection of <see cref="MediaTypeHeaderValue"/> elements supported by
|
||||
/// Gets the mutable collection of media type elements supported by
|
||||
/// this <see cref="OutputFormatter"/>.
|
||||
/// </summary>
|
||||
public IList<MediaTypeHeaderValue> SupportedMediaTypes
|
||||
{
|
||||
get { return _supportedMediaTypes; }
|
||||
}
|
||||
public MediaTypeCollection SupportedMediaTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IReadOnlyList<MediaTypeHeaderValue> GetSupportedContentTypes(
|
||||
MediaTypeHeaderValue contentType,
|
||||
public virtual IReadOnlyList<string> 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<MediaTypeHeaderValue> mediaTypes = null;
|
||||
List<string> 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<MediaTypeHeaderValue>();
|
||||
mediaTypes = new List<string>();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -246,6 +244,33 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// <returns>A task which can write the response body.</returns>
|
||||
public abstract Task WriteResponseBodyAsync(OutputFormatterWriteContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Adds or replaces the charset parameter in a given <paramref name="mediaType"/> with the
|
||||
/// given <paramref name="encoding"/>.
|
||||
/// </summary>
|
||||
/// <param name="mediaType">The <see cref="StringSegment"/> with the media type.</param>
|
||||
/// <param name="encoding">
|
||||
/// The <see cref="Encoding"/> to add or replace in the <paramref name="mediaType"/>.
|
||||
/// </param>
|
||||
/// <returns>The mediaType with the given encoding.</returns>
|
||||
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<StringWithQualityHeaderValue> 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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MediaTypeHeaderValue>();
|
||||
result.ContentTypes = new MediaTypeCollection();
|
||||
}
|
||||
|
||||
result.ContentTypes.Add(MediaTypeHeaderValue.Parse(responseContentType));
|
||||
result.ContentTypes.Add(responseContentType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +158,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// </returns>
|
||||
protected virtual IOutputFormatter SelectFormatter(
|
||||
OutputFormatterWriteContext formatterContext,
|
||||
IList<MediaTypeHeaderValue> contentTypes,
|
||||
MediaTypeCollection contentTypes,
|
||||
IList<IOutputFormatter> 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<MediaTypeSegmentWithQuality> GetMediaTypes(
|
||||
MediaTypeCollection contentTypes,
|
||||
HttpRequest request)
|
||||
{
|
||||
var result = new List<MediaTypeSegmentWithQuality>();
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the <see cref="IOutputFormatter"/> 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<IOutputFormatter> formatters,
|
||||
IList<MediaTypeHeaderValue> sortedAcceptHeaders)
|
||||
IList<MediaTypeSegmentWithQuality> 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<IOutputFormatter> formatters,
|
||||
IList<MediaTypeHeaderValue> 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<MediaTypeHeaderValue> PrepareAcceptValues(IList<MediaTypeHeaderValue> 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<MediaTypeHeaderValue>(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<MediaTypeHeaderValue> 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,
|
||||
|
|
|
|||
|
|
@ -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
|
|||
/// <param name="resolvedContentType">The content type to be used for the response content type header</param>
|
||||
/// <param name="resolvedContentTypeEncoding">Encoding to be used for writing the response</param>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<ILogger, IOutputFormatter, string, Exception> _formatterSelected;
|
||||
private static readonly Action<ILogger, string, Exception> _skippedContentNegotiation;
|
||||
private static readonly Action<ILogger, string, Exception> _noAcceptForNegotiation;
|
||||
private static readonly Action<ILogger, IEnumerable<MediaTypeHeaderValue>, Exception> _noFormatterFromNegotiation;
|
||||
private static readonly Action<ILogger, IEnumerable<MediaTypeSegmentWithQuality>, 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<IEnumerable<MediaTypeHeaderValue>>(
|
||||
_noFormatterFromNegotiation = LoggerMessage.Define<IEnumerable<MediaTypeSegmentWithQuality>>(
|
||||
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<MediaTypeHeaderValue> acceptTypes)
|
||||
public static void NoFormatterFromNegotiation(this ILogger logger, IList<MediaTypeSegmentWithQuality> acceptTypes)
|
||||
{
|
||||
_noFormatterFromNegotiation(logger, acceptTypes, null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
public FilterCollection Filters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Used to specify mapping between the URL Format and corresponding
|
||||
/// <see cref="Net.Http.Headers.MediaTypeHeaderValue"/>.
|
||||
/// Used to specify mapping between the URL Format and corresponding media type.
|
||||
/// </summary>
|
||||
public FormatterMappings FormatterMappings { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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<IOutputFormatter>();
|
||||
ContentTypes = new List<MediaTypeHeaderValue>();
|
||||
ContentTypes = new MediaTypeCollection();
|
||||
}
|
||||
|
||||
public object Value { get; set; }
|
||||
|
||||
public FormatterCollection<IOutputFormatter> Formatters { get; set; }
|
||||
|
||||
public IList<MediaTypeHeaderValue> ContentTypes { get; set; }
|
||||
public MediaTypeCollection ContentTypes { get; set; }
|
||||
|
||||
public Type DeclaredType { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -34,10 +34,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
throw new ArgumentNullException(nameof(fileName));
|
||||
}
|
||||
if (contentType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contentType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -47,18 +43,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <param name="fileName">The path to the file. The path must be an absolute path.</param>
|
||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<MediaTypeHeaderValue>();
|
||||
ContentTypes = new MediaTypeCollection();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -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<MediaTypeHeaderValue> ContentTypes { get; set; }
|
||||
public MediaTypeCollection ContentTypes { get; set; }
|
||||
|
||||
public override void OnResultExecuting(ResultExecutingContext context)
|
||||
{
|
||||
|
|
@ -74,16 +84,17 @@ namespace Microsoft.AspNet.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
private List<MediaTypeHeaderValue> GetContentTypes(string firstArg, string[] args)
|
||||
private MediaTypeCollection GetContentTypes(string firstArg, string[] args)
|
||||
{
|
||||
var completeArgs = new List<string>();
|
||||
completeArgs.Add(firstArg);
|
||||
completeArgs.AddRange(args);
|
||||
var contentTypes = new List<MediaTypeHeaderValue>();
|
||||
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<MediaTypeHeaderValue> contentTypes)
|
||||
public void SetContentTypes(MediaTypeCollection contentTypes)
|
||||
{
|
||||
contentTypes.Clear();
|
||||
foreach (var contentType in ContentTypes)
|
||||
|
|
|
|||
|
|
@ -1034,6 +1034,22 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
return GetString("HttpResponseStreamWriter_StreamNotWritable");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The argument '{0}' is invalid. Empty or null formats are not supported.
|
||||
/// </summary>
|
||||
internal static string FormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat
|
||||
{
|
||||
get { return GetString("FormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The argument '{0}' is invalid. Empty or null formats are not supported.
|
||||
/// </summary>
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -319,4 +319,7 @@
|
|||
<data name="HttpResponseStreamWriter_StreamNotWritable" xml:space="preserve">
|
||||
<value>The stream must support writing.</value>
|
||||
</data>
|
||||
<data name="FormatFormatterMappings_GetMediaTypeMappingForFormat_InvalidFormat" xml:space="preserve">
|
||||
<value>The argument '{0}' is invalid. Empty or null formats are not supported.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
|
@ -37,10 +37,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
throw new ArgumentNullException(nameof(fileName));
|
||||
}
|
||||
if (contentType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contentType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -51,18 +47,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <param name="fileName">The path to the file. The path must be relative/virtual.</param>
|
||||
/// <param name="contentType">The Content-Type header of the response.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// </summary>
|
||||
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();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="JsonResultExecutor"/>.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// <summary>
|
||||
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue ContentType { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="JsonSerializerSettings"/>.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -46,9 +46,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
public IViewEngine ViewEngine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
|
||||
/// Gets or sets the Content-Type header for the response.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue ContentType { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task ExecuteResultAsync(ActionContext context)
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
|
||||
/// Gets or sets the Content-Type header for the response.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue ContentType { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the HTTP status code.
|
||||
|
|
|
|||
|
|
@ -23,12 +23,9 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
|
|||
public class ViewExecutor
|
||||
{
|
||||
/// <summary>
|
||||
/// The default content-type header value for views, <c>text/html; charset=utf8</c>.
|
||||
/// The default content-type header value for views, <c>text/html; charset=utf-8</c>.
|
||||
/// </summary>
|
||||
public static readonly MediaTypeHeaderValue DefaultContentType = new MediaTypeHeaderValue("text/html")
|
||||
{
|
||||
Encoding = Encoding.UTF8
|
||||
}.CopyAsReadOnly();
|
||||
public static readonly string DefaultContentType = "text/html; charset=utf-8";
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ViewExecutor"/>.
|
||||
|
|
@ -122,7 +119,7 @@ namespace Microsoft.AspNet.Mvc.ViewFeatures
|
|||
IView view,
|
||||
ViewDataDictionary viewData,
|
||||
ITempDataDictionary tempData,
|
||||
MediaTypeHeaderValue contentType,
|
||||
string contentType,
|
||||
int? statusCode)
|
||||
{
|
||||
if (actionContext == null)
|
||||
|
|
|
|||
|
|
@ -51,9 +51,9 @@ namespace Microsoft.AspNet.Mvc
|
|||
public IViewEngine ViewEngine { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> representing the Content-Type header of the response.
|
||||
/// Gets or sets the Content-Type header for the response.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue ContentType { get; set; }
|
||||
public string ContentType { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task ExecuteResultAsync(ActionContext context)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<MediaTypeHeaderValue> ContentTypes { get; } = new List<MediaTypeHeaderValue>();
|
||||
public MediaTypeCollection ContentTypes { get; } = new MediaTypeCollection();
|
||||
|
||||
public Type Type { get; set; }
|
||||
|
||||
public void SetContentTypes(IList<MediaTypeHeaderValue> contentTypes)
|
||||
public void SetContentTypes(MediaTypeCollection contentTypes)
|
||||
{
|
||||
contentTypes.Clear();
|
||||
foreach (var contentType in ContentTypes)
|
||||
|
|
|
|||
|
|
@ -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<IHttpBufferingFeature>(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());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<ContentResult>(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<ContentResult>(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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<ObjectResult>(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>();
|
||||
httpContext.Setup(c => c.Response).Returns(new Mock<HttpResponse>().Object);
|
||||
|
|
@ -95,7 +96,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
// Assert
|
||||
var objectResult = Assert.IsType<ObjectResult>(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<ObjectResult>(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>();
|
||||
httpContext.Setup(c => c.Response).Returns(new Mock<HttpResponse>().Object);
|
||||
|
|
@ -330,7 +331,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
// Assert
|
||||
var result = Assert.IsType<ObjectResult>(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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<ArgumentException>("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<ArgumentException>(() => options.SetMediaTypeMappingForFormat(
|
||||
"star",
|
||||
"star",
|
||||
MediaTypeHeaderValue.Parse(format)));
|
||||
Assert.Equal(expected, exception.Message);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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<OutputFormatter>();
|
||||
|
||||
formatter
|
||||
.Setup(f => f.SelectCharacterEncoding(It.IsAny<OutputFormatterWriteContext>()))
|
||||
.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);
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<TestStringOutputFormatter>(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<string[], string, string> ContentTypes
|
||||
public static TheoryData<MediaTypeCollection, string, string> ContentTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
var contentTypes = new string[]
|
||||
var contentTypes = new MediaTypeCollection
|
||||
{
|
||||
"text/plain",
|
||||
"text/xml",
|
||||
"application/json",
|
||||
};
|
||||
|
||||
return new TheoryData<string[], string, string>()
|
||||
return new TheoryData<MediaTypeCollection, string, string>()
|
||||
{
|
||||
// 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<string> 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<MediaTypeHeaderValue>(),
|
||||
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<MediaTypeHeaderValue> contentTypes,
|
||||
MediaTypeCollection contentTypes,
|
||||
IList<IOutputFormatter> formatters)
|
||||
{
|
||||
return base.SelectFormatter(formatterContext, contentTypes, formatters);
|
||||
|
|
@ -593,7 +601,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
protected override IOutputFormatter SelectFormatter(
|
||||
OutputFormatterWriteContext formatterContext,
|
||||
IList<MediaTypeHeaderValue> contentTypes,
|
||||
MediaTypeCollection contentTypes,
|
||||
IList<IOutputFormatter> formatters)
|
||||
{
|
||||
SelectedOutputFormatter = base.SelectFormatter(formatterContext, contentTypes, formatters);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<ContentResult>(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]
|
||||
|
|
|
|||
|
|
@ -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<MediaTypeHeaderValue, string> ViewComponentResultContentTypeData
|
||||
public static TheoryData<string, string> ViewComponentResultContentTypeData
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<MediaTypeHeaderValue, string>
|
||||
return new TheoryData<string, string>
|
||||
{
|
||||
{
|
||||
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,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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<ITempDataDictionary>(),
|
||||
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()));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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<JsonResult>(result);
|
||||
Assert.Same(product, jsonResult.Value);
|
||||
|
||||
Assert.Same(Encoding.UTF8, jsonResult.ContentType.Encoding);
|
||||
Assert.Same(Encoding.UTF8, MediaTypeEncoding.GetEncoding(jsonResult.ContentType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ namespace FiltersWebSite
|
|||
context.Result = new ContentResult()
|
||||
{
|
||||
Content = "4",
|
||||
ContentType = new MediaTypeHeaderValue("text/plain")
|
||||
ContentType = "text/plain"
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace FiltersWebSite
|
|||
context.Result = new ContentResult
|
||||
{
|
||||
Content = "The Action was never executed",
|
||||
ContentType = new MediaTypeHeaderValue("text/plain")
|
||||
ContentType = "text/plain"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace FiltersWebSite
|
|||
return new ContentResult()
|
||||
{
|
||||
Content = content,
|
||||
ContentType = new MediaTypeHeaderValue("text/plain"),
|
||||
ContentType = "text/plain",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue