Refactor of OutputFormattterContext
This commit is contained in:
parent
d584bcabcf
commit
38b65875db
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
|
|
@ -16,18 +15,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// an object of the specified type.
|
||||
/// </summary>
|
||||
/// <param name="context">The formatter context associated with the call.</param>
|
||||
/// <param name="contentType">The desired contentType on the response.</param>
|
||||
/// <returns>True if this <see cref="IOutputFormatter"/> supports the passed in
|
||||
/// <paramref name="contentType"/> and is able to serialize the object
|
||||
/// represent by <paramref name="context"/>'s Object property.
|
||||
/// False otherwise.</returns>
|
||||
bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType);
|
||||
/// <returns>Returns <c>true</c> if the formatter can write the response; <c>false</c> otherwise.</returns>
|
||||
bool CanWriteResult(OutputFormatterCanWriteContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Writes the object represented by <paramref name="context"/>'s Object property.
|
||||
/// </summary>
|
||||
/// <param name="context">The formatter context associated with the call.</param>
|
||||
/// <returns>A Task that serializes the value to the <paramref name="context"/>'s response message.</returns>
|
||||
Task WriteAsync(OutputFormatterContext context);
|
||||
Task WriteAsync(OutputFormatterWriteContext context);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 System;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
/// <summary>
|
||||
/// A context object for <see cref="IOutputFormatter.CanWriteResult(OutputFormatterCanWriteContext)"/>.
|
||||
/// </summary>
|
||||
public abstract class OutputFormatterCanWriteContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="MediaTypeHeaderValue"/> of the content type to write to the response.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An <see cref="IOutputFormatter"/> can set this value when its
|
||||
/// <see cref="IOutputFormatter.CanWriteResult(OutputFormatterCanWriteContext)"/> method is called,
|
||||
/// and expect to see the same value provided in
|
||||
/// <see cref="IOutputFormatter.WriteAsync(OutputFormatterWriteContext)"/>
|
||||
/// </remarks>
|
||||
public virtual MediaTypeHeaderValue ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating that content-negotiation could not find a formatter based on the
|
||||
/// information on the <see cref="Http.HttpRequest"/>.
|
||||
/// </summary>
|
||||
public virtual bool? FailedContentNegotiation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the object to write to the response.
|
||||
/// </summary>
|
||||
public virtual object Object { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="Type"/> of the object to write to the response.
|
||||
/// </summary>
|
||||
public virtual Type ObjectType { get; protected set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
// 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.Text;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information used by a formatter for participating in
|
||||
/// output content negotiation and in writing out the response.
|
||||
/// </summary>
|
||||
public class OutputFormatterContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The return value of the action method.
|
||||
/// </summary>
|
||||
public object Object { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The declared return type of the action.
|
||||
/// </summary>
|
||||
public Type DeclaredType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="HttpContext"/> context associated with the current operation.
|
||||
/// </summary>
|
||||
public HttpContext HttpContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The encoding which is chosen by the selected formatter.
|
||||
/// </summary>
|
||||
public Encoding SelectedEncoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The content type which is chosen by the selected formatter.
|
||||
/// </summary>
|
||||
public MediaTypeHeaderValue SelectedContentType { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a flag to indicate that content-negotiation could not find a formatter based on the
|
||||
/// information on the <see cref="Http.HttpRequest"/>.
|
||||
/// </summary>
|
||||
public bool? FailedContentNegotiation { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// 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.AspNet.Http;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
/// <summary>
|
||||
/// A context object for <see cref="IOutputFormatter.WriteAsync(OutputFormatterWriteContext)"/>.
|
||||
/// </summary>
|
||||
public class OutputFormatterWriteContext : OutputFormatterCanWriteContext
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="OutputFormatterWriteContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="httpContext">The <see cref="Http.HttpContext"/> for the current request.</param>
|
||||
/// <param name="objectType">The <see cref="Type"/> of the object to write to the response.</param>
|
||||
/// <param name="@object">The object to write to the response.</param>
|
||||
public OutputFormatterWriteContext(HttpContext httpContext, Type objectType, object @object)
|
||||
{
|
||||
if (httpContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(httpContext));
|
||||
}
|
||||
|
||||
HttpContext = httpContext;
|
||||
ObjectType = objectType;
|
||||
Object = @object;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="HttpContext"/> context associated with the current operation.
|
||||
/// </summary>
|
||||
public virtual HttpContext HttpContext { get; protected set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -129,7 +129,6 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
|
|||
var formats = GetResponseFormats(
|
||||
action,
|
||||
responseMetadataAttributes,
|
||||
declaredReturnType,
|
||||
runtimeReturnType);
|
||||
|
||||
foreach (var format in formats)
|
||||
|
|
@ -306,8 +305,7 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
|
|||
private IReadOnlyList<ApiResponseFormat> GetResponseFormats(
|
||||
ControllerActionDescriptor action,
|
||||
IApiResponseMetadataProvider[] responseMetadataAttributes,
|
||||
Type declaredType,
|
||||
Type runtimeType)
|
||||
Type type)
|
||||
{
|
||||
var results = new List<ApiResponseFormat>();
|
||||
|
||||
|
|
@ -334,10 +332,7 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
|
|||
var responseFormatMetadataProvider = formatter as IApiResponseFormatMetadataProvider;
|
||||
if (responseFormatMetadataProvider != null)
|
||||
{
|
||||
var supportedTypes = responseFormatMetadataProvider.GetSupportedContentTypes(
|
||||
declaredType,
|
||||
runtimeType,
|
||||
contentType);
|
||||
var supportedTypes = responseFormatMetadataProvider.GetSupportedContentTypes(contentType, type);
|
||||
|
||||
if (supportedTypes != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,25 +11,25 @@ namespace Microsoft.AspNet.Mvc.ApiExplorer
|
|||
/// Provides metadata information about the response format to an <c>IApiDescriptionProvider</c>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An <see cref="Formatters.IOutputFormatter"/> should implement this interface to expose metadata information
|
||||
/// An <see cref="IOutputFormatter"/> should implement this interface to expose metadata information
|
||||
/// to an <c>IApiDescriptionProvider</c>.
|
||||
/// </remarks>
|
||||
public interface IApiResponseFormatMetadataProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a filtered list of content types which are supported by the <see cref="Formatters.IOutputFormatter"/>
|
||||
/// Gets a filtered list of content types which are supported by the <see cref="IOutputFormatter"/>
|
||||
/// for the <paramref name="declaredType"/> and <paramref name="contentType"/>.
|
||||
/// </summary>
|
||||
/// <param name="declaredType">The declared type for which the supported content types are desired.</param>
|
||||
/// <param name="runtimeType">The runtime type for which the supported content types are desired.</param>
|
||||
/// <param name="contentType">
|
||||
/// The content type for which the supported content types are desired, or <c>null</c> if any content
|
||||
/// type can be used.
|
||||
/// </param>
|
||||
/// <returns>Content types which are supported by the <see cref="Formatters.IOutputFormatter"/>.</returns>
|
||||
/// <param name="objectType">
|
||||
/// The <see cref="Type"/> for which the supported content types are desired.
|
||||
/// </param>
|
||||
/// <returns>Content types which are supported by the <see cref="IOutputFormatter"/>.</returns>
|
||||
IReadOnlyList<MediaTypeHeaderValue> GetSupportedContentTypes(
|
||||
Type declaredType,
|
||||
Type runtimeType,
|
||||
MediaTypeHeaderValue contentType);
|
||||
MediaTypeHeaderValue contentType,
|
||||
Type objectType);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
|
|
@ -18,12 +17,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// </summary>
|
||||
public bool TreatNullValueAsNoContent { get; set; } = true;
|
||||
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
/// <inheritdoc />
|
||||
public bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
// ignore the contentType and just look at the content.
|
||||
// This formatter will be selected if the content is null.
|
||||
// We check for Task as a user can directly create an ObjectContentResult with the unwrapped type.
|
||||
if (context.DeclaredType == typeof(void) || context.DeclaredType == typeof(Task))
|
||||
if (context.ObjectType == typeof(void) || context.ObjectType == typeof(Task))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -31,7 +31,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
return TreatNullValueAsNoContent && context.Object == null;
|
||||
}
|
||||
|
||||
public Task WriteAsync(OutputFormatterContext context)
|
||||
/// <inheritdoc />
|
||||
public Task WriteAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
response.ContentLength = 0;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
|
|
@ -13,13 +12,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
public class HttpNotAcceptableOutputFormatter : IOutputFormatter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
return context.FailedContentNegotiation ?? false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task WriteAsync(OutputFormatterContext context)
|
||||
public Task WriteAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
response.StatusCode = StatusCodes.Status406NotAcceptable;
|
||||
|
|
|
|||
|
|
@ -49,21 +49,19 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// <summary>
|
||||
/// Returns a value indicating whether or not the given type can be written by this serializer.
|
||||
/// </summary>
|
||||
/// <param name="declaredType">The declared type.</param>
|
||||
/// <param name="runtimeType">The runtime type.</param>
|
||||
/// <param name="type">The object type.</param>
|
||||
/// <returns><c>true</c> if the type can be written, otherwise <c>false</c>.</returns>
|
||||
protected virtual bool CanWriteType(Type declaredType, Type runtimeType)
|
||||
protected virtual bool CanWriteType(Type type)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IReadOnlyList<MediaTypeHeaderValue> GetSupportedContentTypes(
|
||||
Type declaredType,
|
||||
Type runtimeType,
|
||||
MediaTypeHeaderValue contentType)
|
||||
MediaTypeHeaderValue contentType,
|
||||
Type objectType)
|
||||
{
|
||||
if (!CanWriteType(declaredType, runtimeType))
|
||||
if (!CanWriteType(objectType))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
@ -103,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// <param name="context">The formatter context associated with the call.
|
||||
/// </param>
|
||||
/// <returns>The <see cref="Encoding"/> to use when reading the request or writing the response.</returns>
|
||||
public virtual Encoding SelectCharacterEncoding(OutputFormatterContext context)
|
||||
public virtual Encoding SelectCharacterEncoding(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -112,95 +110,97 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
var request = context.HttpContext.Request;
|
||||
var encoding = MatchAcceptCharacterEncoding(request.GetTypedHeaders().AcceptCharset);
|
||||
if (encoding == null)
|
||||
if (encoding != null)
|
||||
{
|
||||
// Match based on request acceptHeader.
|
||||
MediaTypeHeaderValue requestContentType = null;
|
||||
if (MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType) &&
|
||||
!string.IsNullOrEmpty(requestContentType.Charset))
|
||||
return encoding;
|
||||
}
|
||||
|
||||
var charset = context.ContentType?.Charset;
|
||||
if (charset != null)
|
||||
{
|
||||
for (var i = 0; i < SupportedEncodings.Count; i++)
|
||||
{
|
||||
var requestCharset = requestContentType.Charset;
|
||||
encoding = SupportedEncodings.FirstOrDefault(
|
||||
supportedEncoding => requestCharset.Equals(supportedEncoding.WebName));
|
||||
if (string.Equals(charset, SupportedEncodings[i].WebName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// This is supported.
|
||||
return context.ContentType.Encoding;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
encoding = encoding ?? SupportedEncodings.FirstOrDefault();
|
||||
return encoding;
|
||||
// A formatter for a non-text media-type won't have any supported encodings.
|
||||
return SupportedEncodings.Count > 0 ? SupportedEncodings[0] : null;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public virtual bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var runtimeType = context.Object == null ? null : context.Object.GetType();
|
||||
if (!CanWriteType(context.DeclaredType, runtimeType))
|
||||
|
||||
if (!CanWriteType(context.ObjectType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
MediaTypeHeaderValue mediaType = null;
|
||||
if (contentType == null)
|
||||
|
||||
if (context.ContentType == null)
|
||||
{
|
||||
// If the desired content type is set to null, the current formatter is free to choose the
|
||||
// response media type.
|
||||
mediaType = SupportedMediaTypes.FirstOrDefault();
|
||||
// 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];
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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.
|
||||
mediaType = SupportedMediaTypes.FirstOrDefault(
|
||||
supportedMediaType => supportedMediaType.IsSubsetOf(contentType));
|
||||
}
|
||||
|
||||
if (mediaType != null)
|
||||
{
|
||||
context.SelectedContentType = mediaType;
|
||||
return true;
|
||||
for (var i = 0; i < SupportedMediaTypes.Count; i++)
|
||||
{
|
||||
var mediaType = SupportedMediaTypes[i];
|
||||
if (mediaType.IsSubsetOf(context.ContentType))
|
||||
{
|
||||
context.ContentType = mediaType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task WriteAsync(OutputFormatterContext context)
|
||||
public Task WriteAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
WriteResponseHeaders(context);
|
||||
return WriteResponseBodyAsync(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the headers on <see cref="Microsoft.AspNet.Http.HttpResponse"/> object.
|
||||
/// </summary>
|
||||
/// <param name="context">The formatter context associated with the call.</param>
|
||||
public virtual void WriteResponseHeaders(OutputFormatterContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var selectedMediaType = context.SelectedContentType;
|
||||
|
||||
// If content type is not set then set it based on supported media types.
|
||||
selectedMediaType = selectedMediaType ?? SupportedMediaTypes.FirstOrDefault();
|
||||
var selectedMediaType = context.ContentType;
|
||||
if (selectedMediaType == null)
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatOutputFormatterNoMediaType(GetType().FullName));
|
||||
// If content type is not set then set it based on supported media types.
|
||||
if (SupportedEncodings.Count > 0)
|
||||
{
|
||||
selectedMediaType = SupportedMediaTypes[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatOutputFormatterNoMediaType(GetType().FullName));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the media type as we don't want it to affect the next request
|
||||
// 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
|
||||
|
|
@ -215,16 +215,29 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
var selectedEncoding = SelectCharacterEncoding(context);
|
||||
if (selectedEncoding != null)
|
||||
{
|
||||
context.SelectedEncoding = selectedEncoding;
|
||||
|
||||
// Override the content type value even if one already existed.
|
||||
selectedMediaType.Charset = selectedEncoding.WebName;
|
||||
selectedMediaType.Encoding = selectedEncoding;
|
||||
}
|
||||
|
||||
context.SelectedContentType = context.SelectedContentType ?? selectedMediaType;
|
||||
context.ContentType = selectedMediaType;
|
||||
|
||||
WriteResponseHeaders(context);
|
||||
return WriteResponseBodyAsync(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the headers on <see cref="Microsoft.AspNet.Http.HttpResponse"/> object.
|
||||
/// </summary>
|
||||
/// <param name="context">The formatter context associated with the call.</param>
|
||||
public virtual void WriteResponseHeaders(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var response = context.HttpContext.Response;
|
||||
response.ContentType = selectedMediaType.ToString();
|
||||
response.ContentType = context.ContentType?.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -232,7 +245,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// </summary>
|
||||
/// <param name="context">The formatter context associated with the call.</param>
|
||||
/// <returns>A task which can write the response body.</returns>
|
||||
public abstract Task WriteResponseBodyAsync(OutputFormatterContext context);
|
||||
public abstract Task WriteResponseBodyAsync(OutputFormatterWriteContext context);
|
||||
|
||||
private Encoding MatchAcceptCharacterEncoding(IList<StringWithQualityHeaderValue> acceptCharsetHeaders)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
|
|
@ -15,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
public class StreamOutputFormatter : IOutputFormatter
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -25,7 +24,6 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
// Ignore the passed in content type, if the object is a Stream.
|
||||
if (context.Object is Stream)
|
||||
{
|
||||
context.SelectedContentType = contentType;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -33,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task WriteAsync(OutputFormatterContext context)
|
||||
public async Task WriteAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -44,9 +42,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
{
|
||||
var response = context.HttpContext.Response;
|
||||
|
||||
if (context.SelectedContentType != null)
|
||||
if (context.ContentType != null)
|
||||
{
|
||||
response.ContentType = context.SelectedContentType.ToString();
|
||||
response.ContentType = context.ContentType.ToString();
|
||||
}
|
||||
|
||||
var bufferingFeature = context.HttpContext.Features.Get<IHttpBufferingFeature>();
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/plain").CopyAsReadOnly());
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
// Ignore the passed in content type, if the object is string
|
||||
// always return it as a text/plain format.
|
||||
if (context.DeclaredType == typeof(string))
|
||||
if (context.ObjectType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
return false;
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
var response = context.HttpContext.Response;
|
||||
|
||||
return response.WriteAsync(valueAsString, context.SelectedEncoding);
|
||||
return response.WriteAsync(valueAsString, context.ContentType?.Encoding ?? Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,13 +103,13 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
formatters = GetDefaultFormatters();
|
||||
}
|
||||
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
var objectType = result.DeclaredType;
|
||||
if (objectType == null || objectType == typeof(object))
|
||||
{
|
||||
DeclaredType = result.DeclaredType,
|
||||
HttpContext = context.HttpContext,
|
||||
Object = result.Value,
|
||||
objectType = result.Value?.GetType();
|
||||
};
|
||||
|
||||
var formatterContext = new OutputFormatterWriteContext(context.HttpContext, objectType, result.Value);
|
||||
var selectedFormatter = SelectFormatter(formatterContext, result.ContentTypes, formatters);
|
||||
if (selectedFormatter == null)
|
||||
{
|
||||
|
|
@ -124,7 +124,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
"Selected output formatter '{OutputFormatter}' and content type " +
|
||||
"'{ContentType}' to write the response.",
|
||||
selectedFormatter.GetType().FullName,
|
||||
formatterContext.SelectedContentType);
|
||||
formatterContext.ContentType);
|
||||
|
||||
result.OnFormatting(context);
|
||||
return selectedFormatter.WriteAsync(formatterContext);
|
||||
|
|
@ -133,7 +133,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// <summary>
|
||||
/// Selects the <see cref="IOutputFormatter"/> to write the response.
|
||||
/// </summary>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterContext"/>.</param>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterWriteContext"/>.</param>
|
||||
/// <param name="contentTypes">
|
||||
/// The list of content types provided by <see cref="ObjectResult.ContentTypes"/>.
|
||||
/// </param>
|
||||
|
|
@ -144,7 +144,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// The selected <see cref="IOutputFormatter"/> or <c>null</c> if no formatter can write the response.
|
||||
/// </returns>
|
||||
protected virtual IOutputFormatter SelectFormatter(
|
||||
OutputFormatterContext formatterContext,
|
||||
OutputFormatterWriteContext formatterContext,
|
||||
IList<MediaTypeHeaderValue> contentTypes,
|
||||
IEnumerable<IOutputFormatter> formatters)
|
||||
{
|
||||
|
|
@ -249,7 +249,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterContext"/>.</param>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterWriteContext"/>.</param>
|
||||
/// <param name="formatters">
|
||||
/// The list of <see cref="IOutputFormatter"/> instances to consider.
|
||||
/// </param>
|
||||
|
|
@ -257,7 +257,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// The selected <see cref="IOutputFormatter"/> or <c>null</c> if no formatter can write the response.
|
||||
/// </returns>
|
||||
protected virtual IOutputFormatter SelectFormatterNotUsingAcceptHeaders(
|
||||
OutputFormatterContext formatterContext,
|
||||
OutputFormatterWriteContext formatterContext,
|
||||
IEnumerable<IOutputFormatter> formatters)
|
||||
{
|
||||
if (formatterContext == null)
|
||||
|
|
@ -272,7 +272,8 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
foreach (var formatter in formatters)
|
||||
{
|
||||
if (formatter.CanWriteResult(formatterContext, contentType: null))
|
||||
formatterContext.ContentType = null;
|
||||
if (formatter.CanWriteResult(formatterContext))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
|
|
@ -285,7 +286,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// Selects the <see cref="IOutputFormatter"/> to write the response based on the content type values
|
||||
/// present in <paramref name="sortedAcceptHeaders"/>.
|
||||
/// </summary>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterContext"/>.</param>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterWriteContext"/>.</param>
|
||||
/// <param name="formatters">
|
||||
/// The list of <see cref="IOutputFormatter"/> instances to consider.
|
||||
/// </param>
|
||||
|
|
@ -296,7 +297,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// The selected <see cref="IOutputFormatter"/> or <c>null</c> if no formatter can write the response.
|
||||
/// </returns>
|
||||
protected virtual IOutputFormatter SelectFormatterUsingSortedAcceptHeaders(
|
||||
OutputFormatterContext formatterContext,
|
||||
OutputFormatterWriteContext formatterContext,
|
||||
IEnumerable<IOutputFormatter> formatters,
|
||||
IEnumerable<MediaTypeHeaderValue> sortedAcceptHeaders)
|
||||
{
|
||||
|
|
@ -314,29 +315,27 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
{
|
||||
throw new ArgumentNullException(nameof(sortedAcceptHeaders));
|
||||
}
|
||||
|
||||
IOutputFormatter selectedFormatter = null;
|
||||
|
||||
foreach (var contentType in sortedAcceptHeaders)
|
||||
{
|
||||
// Loop through each of the formatters and see if any one will support this
|
||||
// mediaType Value.
|
||||
selectedFormatter = formatters.FirstOrDefault(
|
||||
formatter => formatter.CanWriteResult(formatterContext, contentType));
|
||||
if (selectedFormatter != null)
|
||||
foreach (var formatter in formatters)
|
||||
{
|
||||
// we found our match.
|
||||
break;
|
||||
formatterContext.ContentType = contentType;
|
||||
if (formatter.CanWriteResult(formatterContext))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selectedFormatter;
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Selects the <see cref="IOutputFormatter"/> to write the response based on the content type values
|
||||
/// present in <paramref name="acceptableContentTypes"/>.
|
||||
/// </summary>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterContext"/>.</param>
|
||||
/// <param name="formatterContext">The <see cref="OutputFormatterWriteContext"/>.</param>
|
||||
/// <param name="formatters">
|
||||
/// The list of <see cref="IOutputFormatter"/> instances to consider.
|
||||
/// </param>
|
||||
|
|
@ -347,7 +346,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
/// The selected <see cref="IOutputFormatter"/> or <c>null</c> if no formatter can write the response.
|
||||
/// </returns>
|
||||
protected virtual IOutputFormatter SelectFormatterUsingAnyAcceptableContentType(
|
||||
OutputFormatterContext formatterContext,
|
||||
OutputFormatterWriteContext formatterContext,
|
||||
IEnumerable<IOutputFormatter> formatters,
|
||||
IEnumerable<MediaTypeHeaderValue> acceptableContentTypes)
|
||||
{
|
||||
|
|
@ -366,15 +365,23 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
throw new ArgumentNullException(nameof(acceptableContentTypes));
|
||||
}
|
||||
|
||||
var selectedFormatter = formatters.FirstOrDefault(
|
||||
formatter => acceptableContentTypes.Any(
|
||||
contentType => formatter.CanWriteResult(formatterContext, contentType)));
|
||||
foreach (var formatter in formatters)
|
||||
{
|
||||
foreach (var contentType in acceptableContentTypes)
|
||||
{
|
||||
formatterContext.ContentType = contentType;
|
||||
if (formatter.CanWriteResult(formatterContext))
|
||||
{
|
||||
return formatter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return selectedFormatter;
|
||||
return null;
|
||||
}
|
||||
|
||||
private IEnumerable<MediaTypeHeaderValue> GetSortedAcceptHeaderMediaTypes(
|
||||
OutputFormatterContext formatterContext)
|
||||
OutputFormatterWriteContext formatterContext)
|
||||
{
|
||||
var request = formatterContext.HttpContext.Request;
|
||||
var incomingAcceptHeaderMediaTypes = request.GetTypedHeaders().Accept ?? new MediaTypeHeaderValue[] { };
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
return JsonSerializer.Create(SerializerSettings);
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
}
|
||||
|
||||
var response = context.HttpContext.Response;
|
||||
var selectedEncoding = context.SelectedEncoding;
|
||||
var selectedEncoding = context.ContentType?.Encoding ?? Encoding.UTF8;
|
||||
|
||||
using (var writer = new HttpResponseStreamWriter(response.Body, selectedEncoding))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using System.Threading.Tasks;
|
|||
using System.Xml;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Xml;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Xml.Internal;
|
||||
using Microsoft.AspNet.Mvc.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
|
|
@ -87,25 +88,6 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the object to be serialized.
|
||||
/// </summary>
|
||||
/// <param name="declaredType">The declared type.</param>
|
||||
/// <param name="runtimeType">The runtime type.</param>
|
||||
/// <returns>The type of the object to be serialized.</returns>
|
||||
protected virtual Type ResolveType(Type declaredType, Type runtimeType)
|
||||
{
|
||||
if (declaredType == null || declaredType == typeof(object))
|
||||
{
|
||||
if (runtimeType != null)
|
||||
{
|
||||
return runtimeType;
|
||||
}
|
||||
}
|
||||
|
||||
return declaredType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type to be serialized.
|
||||
/// </summary>
|
||||
|
|
@ -113,16 +95,21 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// <returns>The original or wrapped type provided by any <see cref="IWrapperProvider"/>s.</returns>
|
||||
protected virtual Type GetSerializableType(Type type)
|
||||
{
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(
|
||||
new WrapperProviderContext(type, isSerialization: true));
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext(
|
||||
type,
|
||||
isSerialization: true));
|
||||
|
||||
return wrapperProvider?.WrappingType ?? type;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool CanWriteType(Type declaredType, Type runtimeType)
|
||||
protected override bool CanWriteType(Type type)
|
||||
{
|
||||
var type = ResolveType(declaredType, runtimeType);
|
||||
if (type == null)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -185,41 +172,37 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
var tempWriterSettings = WriterSettings.Clone();
|
||||
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||
var writerSettings = WriterSettings.Clone();
|
||||
writerSettings.Encoding = context.ContentType?.Encoding ?? Encoding.UTF8;
|
||||
|
||||
using (var xmlWriter = CreateXmlWriter(context.HttpContext.Response.Body, tempWriterSettings))
|
||||
var value = context.Object;
|
||||
|
||||
using (var xmlWriter = CreateXmlWriter(context.HttpContext.Response.Body, writerSettings))
|
||||
{
|
||||
var obj = context.Object;
|
||||
var runtimeType = obj?.GetType();
|
||||
|
||||
var resolvedType = ResolveType(context.DeclaredType, runtimeType);
|
||||
|
||||
var wrappingType = GetSerializableType(resolvedType);
|
||||
var wrappingType = GetSerializableType(context.ObjectType);
|
||||
|
||||
// Wrap the object only if there is a wrapping type.
|
||||
if (wrappingType != null && wrappingType != resolvedType)
|
||||
if (wrappingType != null && wrappingType != context.ObjectType)
|
||||
{
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(
|
||||
new WrapperProviderContext(
|
||||
declaredType: resolvedType,
|
||||
isSerialization: true));
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext(
|
||||
declaredType: context.ObjectType,
|
||||
isSerialization: true));
|
||||
|
||||
obj = wrapperProvider.Wrap(obj);
|
||||
value = wrapperProvider.Wrap(value);
|
||||
}
|
||||
|
||||
var dataContractSerializer = GetCachedSerializer(wrappingType);
|
||||
dataContractSerializer.WriteObject(xmlWriter, obj);
|
||||
dataContractSerializer.WriteObject(xmlWriter, value);
|
||||
}
|
||||
|
||||
return Task.FromResult(true);
|
||||
return TaskCache.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ using System.Xml;
|
|||
using System.Xml.Serialization;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Xml;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Xml.Internal;
|
||||
using Microsoft.AspNet.Mvc.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters
|
||||
{
|
||||
|
|
@ -66,25 +67,6 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// </summary>
|
||||
public XmlWriterSettings WriterSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the object to be serialized.
|
||||
/// </summary>
|
||||
/// <param name="declaredType">The declared type of the object.</param>
|
||||
/// <param name="runtimeType">The runtime type of the object</param>
|
||||
/// <returns>A type that needs to be serialized.</returns>
|
||||
protected virtual Type ResolveType(Type declaredType, Type runtimeType)
|
||||
{
|
||||
if (declaredType == null || declaredType == typeof(object))
|
||||
{
|
||||
if (runtimeType != null)
|
||||
{
|
||||
return runtimeType;
|
||||
}
|
||||
}
|
||||
|
||||
return declaredType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type to be serialized.
|
||||
/// </summary>
|
||||
|
|
@ -92,16 +74,21 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// <returns>The original or wrapped type provided by any <see cref="IWrapperProvider"/>.</returns>
|
||||
protected virtual Type GetSerializableType(Type type)
|
||||
{
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(
|
||||
new WrapperProviderContext(type, isSerialization: true));
|
||||
if (type == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(type));
|
||||
}
|
||||
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext(
|
||||
type,
|
||||
isSerialization: true));
|
||||
|
||||
return wrapperProvider?.WrappingType ?? type;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool CanWriteType(Type declaredType, Type runtimeType)
|
||||
protected override bool CanWriteType(Type type)
|
||||
{
|
||||
var type = ResolveType(declaredType, runtimeType);
|
||||
if (type == null)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -160,7 +147,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
|
|
@ -169,34 +156,30 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
var response = context.HttpContext.Response;
|
||||
|
||||
var tempWriterSettings = WriterSettings.Clone();
|
||||
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||
var writerSettings = WriterSettings.Clone();
|
||||
writerSettings.Encoding = context.ContentType.Encoding ?? Encoding.UTF8;
|
||||
|
||||
using (var xmlWriter = CreateXmlWriter(context.HttpContext.Response.Body, tempWriterSettings))
|
||||
var value = context.Object;
|
||||
|
||||
using (var xmlWriter = CreateXmlWriter(context.HttpContext.Response.Body, writerSettings))
|
||||
{
|
||||
var obj = context.Object;
|
||||
var runtimeType = obj?.GetType();
|
||||
|
||||
var resolvedType = ResolveType(context.DeclaredType, runtimeType);
|
||||
|
||||
var wrappingType = GetSerializableType(resolvedType);
|
||||
var wrappingType = GetSerializableType(context.ObjectType);
|
||||
|
||||
// Wrap the object only if there is a wrapping type.
|
||||
if (wrappingType != null && wrappingType != resolvedType)
|
||||
if (wrappingType != null && wrappingType != context.ObjectType)
|
||||
{
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(
|
||||
new WrapperProviderContext(
|
||||
declaredType: resolvedType,
|
||||
isSerialization: true));
|
||||
var wrapperProvider = WrapperProviderFactories.GetWrapperProvider(new WrapperProviderContext(
|
||||
declaredType: wrappingType,
|
||||
isSerialization: true));
|
||||
|
||||
obj = wrapperProvider.Wrap(obj);
|
||||
value = wrapperProvider.Wrap(value);
|
||||
}
|
||||
|
||||
var xmlSerializer = GetCachedSerializer(wrappingType);
|
||||
xmlSerializer.Serialize(xmlWriter, obj);
|
||||
xmlSerializer.Serialize(xmlWriter, value);
|
||||
}
|
||||
|
||||
return Task.FromResult(true);
|
||||
return TaskCache.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
|||
{
|
||||
public class HttpResponseMessageOutputFormatter : IOutputFormatter
|
||||
{
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
return context.Object is HttpResponseMessage;
|
||||
}
|
||||
|
||||
public async Task WriteAsync(OutputFormatterContext context)
|
||||
public async Task WriteAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
|
||||
|
|
|
|||
|
|
@ -1360,24 +1360,24 @@ namespace Microsoft.AspNet.Mvc.Description
|
|||
{
|
||||
public List<Type> SupportedTypes { get; } = new List<Type>();
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
protected override bool CanWriteType(Type declaredType, Type actualType)
|
||||
protected override bool CanWriteType(Type type)
|
||||
{
|
||||
if (SupportedTypes.Count == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if ((actualType ?? declaredType) == null)
|
||||
else if (type == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SupportedTypes.Contains(actualType ?? declaredType);
|
||||
return SupportedTypes.Contains(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1988,12 +1988,12 @@ namespace Microsoft.AspNet.Mvc.Controllers
|
|||
|
||||
var formatter = new Mock<IOutputFormatter>();
|
||||
formatter
|
||||
.Setup(f => f.CanWriteResult(It.IsAny<OutputFormatterContext>(), It.IsAny<MediaTypeHeaderValue>()))
|
||||
.Setup(f => f.CanWriteResult(It.IsAny<OutputFormatterCanWriteContext>()))
|
||||
.Returns(true);
|
||||
|
||||
formatter
|
||||
.Setup(f => f.WriteAsync(It.IsAny<OutputFormatterContext>()))
|
||||
.Returns<OutputFormatterContext>(async c =>
|
||||
.Setup(f => f.WriteAsync(It.IsAny<OutputFormatterWriteContext>()))
|
||||
.Returns<OutputFormatterWriteContext>(async c =>
|
||||
{
|
||||
await c.HttpContext.Response.WriteAsync(c.Object.ToString());
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
private class TestOutputFormatter : OutputFormatter
|
||||
{
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
private class AnotherTestOutputFormatter : OutputFormatter
|
||||
{
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(null)]
|
||||
public void CanWriteResult_ReturnsFalse_WhenConnegHasntFailed(bool? connegFailedValue)
|
||||
public void CanWriteResult_ReturnsFalse_WhenConnegHasntFailed(bool? failedContentNegotiation)
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new HttpNotAcceptableOutputFormatter();
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null)
|
||||
{
|
||||
FailedContentNegotiation = connegFailedValue,
|
||||
FailedContentNegotiation = failedContentNegotiation,
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(context, contentType: null);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
|
@ -36,13 +36,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
// Arrange
|
||||
var formatter = new HttpNotAcceptableOutputFormatter();
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null)
|
||||
{
|
||||
FailedContentNegotiation = true,
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(context, contentType: null);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -54,10 +54,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
// Arrange
|
||||
var formatter = new HttpNotAcceptableOutputFormatter();
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(context);
|
||||
|
|
|
|||
|
|
@ -40,18 +40,18 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
bool useNonNullContentType)
|
||||
{
|
||||
// Arrange
|
||||
var typeToUse = declaredTypeAsString ? typeof(string) : typeof(object);
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
{
|
||||
Object = value,
|
||||
DeclaredType = typeToUse,
|
||||
HttpContext = null,
|
||||
};
|
||||
var type = declaredTypeAsString ? typeof(string) : typeof(object);
|
||||
var contentType = useNonNullContentType ? MediaTypeHeaderValue.Parse("text/plain") : null;
|
||||
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), type, value)
|
||||
{
|
||||
ContentType = contentType,
|
||||
};
|
||||
|
||||
var formatter = new HttpNoContentOutputFormatter();
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(formatterContext, contentType);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
|
|
@ -63,17 +63,18 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
public void CanWriteResult_ReturnsTrue_IfReturnTypeIsVoidOrTask(Type declaredType)
|
||||
{
|
||||
// Arrange
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
var context = new OutputFormatterWriteContext(
|
||||
new DefaultHttpContext(),
|
||||
declaredType,
|
||||
"Something non null.")
|
||||
{
|
||||
Object = "Something non null.",
|
||||
DeclaredType = declaredType,
|
||||
HttpContext = null,
|
||||
ContentType = MediaTypeHeaderValue.Parse("text/plain"),
|
||||
};
|
||||
var contentType = MediaTypeHeaderValue.Parse("text/plain");
|
||||
|
||||
var formatter = new HttpNoContentOutputFormatter();
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(formatterContext, contentType);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -89,21 +90,21 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
bool expected)
|
||||
{
|
||||
// Arrange
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
var context = new OutputFormatterWriteContext(
|
||||
new DefaultHttpContext(),
|
||||
typeof(string),
|
||||
value)
|
||||
{
|
||||
Object = value,
|
||||
DeclaredType = typeof(string),
|
||||
HttpContext = null,
|
||||
ContentType = MediaTypeHeaderValue.Parse("text/plain"),
|
||||
};
|
||||
|
||||
var contentType = MediaTypeHeaderValue.Parse("text/plain");
|
||||
var formatter = new HttpNoContentOutputFormatter()
|
||||
{
|
||||
TreatNullValueAsNoContent = treatNullValueAsNoContent
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(formatterContext, contentType);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, result);
|
||||
|
|
@ -113,20 +114,15 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
public async Task WriteAsync_WritesTheStatusCode204()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), typeof(string), @object: null);
|
||||
|
||||
var formatter = new HttpNoContentOutputFormatter();
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(formatterContext);
|
||||
await formatter.WriteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(StatusCodes.Status204NoContent, httpContext.Response.StatusCode);
|
||||
Assert.Equal(StatusCodes.Status204NoContent, context.HttpContext.Response.StatusCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -136,15 +132,12 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Response.StatusCode = StatusCodes.Status201Created;
|
||||
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(httpContext, typeof(string), @object: null);
|
||||
|
||||
var formatter = new HttpNoContentOutputFormatter();
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(formatterContext);
|
||||
await formatter.WriteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(StatusCodes.Status201Created, httpContext.Response.StatusCode);
|
||||
|
|
|
|||
|
|
@ -20,22 +20,16 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
get
|
||||
{
|
||||
// string acceptEncodings, string requestEncoding, string[] supportedEncodings, string expectedEncoding
|
||||
yield return new object[] { "", null, new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
yield return new object[] { "", "utf-16", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
yield return new object[] { "", new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
|
||||
yield return new object[] { "utf-8", null, new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
yield return new object[] { "utf-16", "utf-8", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
yield return new object[] { "utf-16; q=0.5", "utf-8", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
yield return new object[] { "utf-8", new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
yield return new object[] { "utf-16", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
yield return new object[] { "utf-16; q=0.5", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
|
||||
yield return new object[] { "utf-8; q=0.0", null, new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
yield return new object[] { "utf-8; q=0.0", "utf-16", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
yield return new object[]
|
||||
{ "utf-8; q=0.0, utf-16; q=0.0", "utf-16", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
yield return new object[]
|
||||
{ "utf-8; q=0.0, utf-16; q=0.0", null, new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
yield return new object[] { "utf-8; q=0.0", new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
yield return new object[] { "utf-8; q=0.0, utf-16; q=0.0", new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
|
||||
yield return new object[] { "*; q=0.0", null, new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
yield return new object[] { "*; q=0.0", "utf-16", new string[] { "utf-8", "utf-16" }, "utf-16" };
|
||||
yield return new object[] { "*; q=0.0", new string[] { "utf-8", "utf-16" }, "utf-8" };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -43,16 +37,15 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
[MemberData(nameof(SelectResponseCharacterEncodingData))]
|
||||
public void SelectResponseCharacterEncoding_SelectsEncoding(
|
||||
string acceptCharsetHeaders,
|
||||
string requestEncoding,
|
||||
string[] supportedEncodings,
|
||||
string expectedEncoding)
|
||||
{
|
||||
// Arrange
|
||||
var mockHttpContext = new Mock<HttpContext>();
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
var httpRequest = new DefaultHttpContext().Request;
|
||||
httpRequest.Headers["Accept-Charset"] = acceptCharsetHeaders;
|
||||
httpRequest.ContentType = "application/acceptCharset;charset=" + requestEncoding;
|
||||
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
||||
httpRequest.Headers[HeaderNames.AcceptCharset] = acceptCharsetHeaders;
|
||||
httpRequest.Headers[HeaderNames.Accept] = "application/acceptCharset";
|
||||
httpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
||||
|
||||
var formatter = new TestOutputFormatter();
|
||||
foreach (string supportedEncoding in supportedEncodings)
|
||||
|
|
@ -60,15 +53,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
formatter.SupportedEncodings.Add(Encoding.GetEncoding(supportedEncoding));
|
||||
}
|
||||
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
var context = new OutputFormatterWriteContext(httpContext.Object, typeof(string), "someValue")
|
||||
{
|
||||
Object = "someValue",
|
||||
HttpContext = mockHttpContext.Object,
|
||||
DeclaredType = typeof(string)
|
||||
ContentType = MediaTypeHeaderValue.Parse(httpRequest.Headers[HeaderNames.Accept]),
|
||||
};
|
||||
|
||||
// Act
|
||||
var actualEncoding = formatter.SelectCharacterEncoding(formatterContext);
|
||||
var actualEncoding = formatter.SelectCharacterEncoding(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(Encoding.GetEncoding(expectedEncoding), actualEncoding);
|
||||
|
|
@ -86,43 +77,20 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
formatter.SupportedMediaTypes.Clear();
|
||||
formatter.SupportedMediaTypes.Add(testContentType);
|
||||
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null)
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
ContentType = testContentType,
|
||||
};
|
||||
|
||||
// Act
|
||||
formatter.WriteResponseHeaders(formatterContext);
|
||||
formatter.WriteResponseHeaders(context);
|
||||
|
||||
// Assert
|
||||
Assert.Null(formatterContext.SelectedEncoding);
|
||||
Assert.Equal(testContentType, formatterContext.SelectedContentType);
|
||||
Assert.Null(context.ContentType.Encoding);
|
||||
Assert.Equal(testContentType, context.ContentType);
|
||||
|
||||
// If we had set an encoding, it would be part of the content type header
|
||||
Assert.Equal(testContentType, formatterContext.HttpContext.Response.GetTypedHeaders().ContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WriteResponseContentHeaders_NoSelectedContentType_SetsOutputFormatterContext()
|
||||
{
|
||||
// Arrange
|
||||
var testFormatter = new DoesNotSetContext();
|
||||
var testContentType = MediaTypeHeaderValue.Parse("application/doesNotSetContext");
|
||||
var formatterContext = new OutputFormatterContext();
|
||||
var mockHttpContext = new Mock<HttpContext>();
|
||||
var httpRequest = new DefaultHttpContext().Request;
|
||||
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
||||
mockHttpContext.SetupProperty(o => o.Response.ContentType);
|
||||
formatterContext.HttpContext = mockHttpContext.Object;
|
||||
|
||||
// Act
|
||||
testFormatter.WriteResponseHeaders(formatterContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(Encoding.Unicode.WebName, formatterContext.SelectedEncoding.WebName);
|
||||
Assert.Equal(Encoding.Unicode, formatterContext.SelectedEncoding);
|
||||
Assert.Equal("application/doesNotSetContext; charset=" + Encoding.Unicode.WebName,
|
||||
formatterContext.SelectedContentType.ToString());
|
||||
Assert.Equal(testContentType, context.HttpContext.Response.GetTypedHeaders().ContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -133,31 +101,31 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
formatter.SupportedMediaTypes.Clear();
|
||||
var mediaType = new MediaTypeHeaderValue("image/png");
|
||||
formatter.SupportedMediaTypes.Add(mediaType);
|
||||
var formatterContext = new OutputFormatterContext();
|
||||
formatterContext.HttpContext = new DefaultHttpContext();
|
||||
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(formatterContext);
|
||||
await formatter.WriteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.NotSame(mediaType, formatterContext.SelectedContentType);
|
||||
Assert.NotSame(mediaType, context.ContentType);
|
||||
Assert.Null(mediaType.Charset);
|
||||
Assert.Equal("image/png; charset=utf-8", formatterContext.SelectedContentType.ToString());
|
||||
Assert.Equal("image/png; charset=utf-8", context.ContentType.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanWriteResult_ForNullContentType_UsesFirstEntryInSupportedContentTypes()
|
||||
{
|
||||
// Arrange
|
||||
var context = new OutputFormatterContext();
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
var formatter = new TestOutputFormatter();
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(context, null);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.Equal(formatter.SupportedMediaTypes[0].ToString(), context.SelectedContentType.ToString());
|
||||
Assert.Equal(formatter.SupportedMediaTypes[0].ToString(), context.ContentType.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -165,16 +133,11 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
{
|
||||
// Arrange
|
||||
var formatter = new TypeSpecificFormatter();
|
||||
|
||||
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json"));
|
||||
|
||||
formatter.SupportedTypes.Add(typeof(int));
|
||||
|
||||
// Act
|
||||
var contentTypes = formatter.GetSupportedContentTypes(
|
||||
declaredType: typeof(string),
|
||||
runtimeType: typeof(string),
|
||||
contentType: null);
|
||||
var contentTypes = formatter.GetSupportedContentTypes(contentType: null, objectType: typeof(string));
|
||||
|
||||
// Assert
|
||||
Assert.Null(contentTypes);
|
||||
|
|
@ -184,18 +147,17 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
public void CanWrite_ReturnsFalse_ForUnsupportedType()
|
||||
{
|
||||
// Arrange
|
||||
var context = new OutputFormatterContext();
|
||||
context.DeclaredType = typeof(string);
|
||||
context.Object = "Hello, world!";
|
||||
|
||||
var formatter = new TypeSpecificFormatter();
|
||||
|
||||
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json"));
|
||||
|
||||
formatter.SupportedTypes.Add(typeof(int));
|
||||
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(),typeof(string), "Hello, world!")
|
||||
{
|
||||
ContentType = formatter.SupportedMediaTypes[0],
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(context, formatter.SupportedMediaTypes[0]);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
|
@ -206,13 +168,12 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
{
|
||||
// Arrange
|
||||
var formatter = new TestOutputFormatter();
|
||||
|
||||
formatter.SupportedMediaTypes.Clear();
|
||||
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/json"));
|
||||
formatter.SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xml"));
|
||||
|
||||
// Act
|
||||
var contentTypes = formatter.GetSupportedContentTypes(typeof(int), typeof(int), contentType: null);
|
||||
var contentTypes = formatter.GetSupportedContentTypes(contentType: null, objectType: typeof(string));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, contentTypes.Count);
|
||||
|
|
@ -232,9 +193,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
// Act
|
||||
var contentTypes = formatter.GetSupportedContentTypes(
|
||||
typeof(int),
|
||||
typeof(int),
|
||||
contentType: MediaTypeHeaderValue.Parse("application/*"));
|
||||
MediaTypeHeaderValue.Parse("application/*"),
|
||||
typeof(int));
|
||||
|
||||
// Assert
|
||||
var contentType = Assert.Single(contentTypes);
|
||||
|
|
@ -253,9 +213,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
// Act
|
||||
var contentTypes = formatter.GetSupportedContentTypes(
|
||||
typeof(int),
|
||||
typeof(int),
|
||||
contentType: MediaTypeHeaderValue.Parse("application/xml"));
|
||||
MediaTypeHeaderValue.Parse("application/xml"),
|
||||
typeof(int));
|
||||
|
||||
// Assert
|
||||
Assert.Null(contentTypes);
|
||||
|
|
@ -271,10 +230,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
formatter.SupportedMediaTypes.Clear();
|
||||
|
||||
// Act
|
||||
var contentTypes = formatter.GetSupportedContentTypes(
|
||||
typeof(int),
|
||||
typeof(int),
|
||||
contentType: null);
|
||||
var contentTypes = formatter.GetSupportedContentTypes(contentType: null, objectType: typeof(int));
|
||||
|
||||
// Assert
|
||||
Assert.Null(contentTypes);
|
||||
|
|
@ -284,12 +240,12 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
{
|
||||
public List<Type> SupportedTypes { get; } = new List<Type>();
|
||||
|
||||
protected override bool CanWriteType(Type declaredType, Type runtimeType)
|
||||
protected override bool CanWriteType(Type type)
|
||||
{
|
||||
return SupportedTypes.Contains(declaredType ?? runtimeType);
|
||||
return SupportedTypes.Contains(type);
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -302,7 +258,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/acceptCharset"));
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
|
@ -316,14 +272,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
SupportedEncodings.Add(Encoding.Unicode);
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
// Do not set the selected media Type.
|
||||
// The WriteResponseHeaders should do it for you.
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
|
@ -337,7 +293,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
SupportedEncodings.Add(Encoding.UTF8);
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,46 +17,40 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
[Theory]
|
||||
[InlineData(typeof(Stream), "text/plain")]
|
||||
[InlineData(typeof(Stream), null)]
|
||||
[InlineData(typeof(object), "text/plain")]
|
||||
[InlineData(typeof(object), null)]
|
||||
[InlineData(typeof(IActionResult), "text/plain")]
|
||||
[InlineData(typeof(IActionResult), null)]
|
||||
public void CanWriteResult_ReturnsTrue_ForStreams(Type declaredType, string contentType)
|
||||
public void CanWriteResult_ReturnsTrue_ForStreams(Type type, string contentType)
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new StreamOutputFormatter();
|
||||
var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType);
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), type, new MemoryStream())
|
||||
{
|
||||
DeclaredType = declaredType,
|
||||
Object = new MemoryStream()
|
||||
ContentType = contentTypeHeader,
|
||||
};
|
||||
|
||||
// Act
|
||||
var canWrite = formatter.CanWriteResult(formatterContext, contentTypeHeader);
|
||||
var canWrite = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.True(canWrite);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(object), "text/plain")]
|
||||
[InlineData(typeof(object), null)]
|
||||
[InlineData(typeof(SimplePOCO), "text/plain")]
|
||||
[InlineData(typeof(SimplePOCO), null)]
|
||||
public void CanWriteResult_OnlyActsOnStreams_IgnoringContentType(Type declaredType, string contentType)
|
||||
public void CanWriteResult_OnlyActsOnStreams_IgnoringContentType(Type type, string contentType)
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new StreamOutputFormatter();
|
||||
var contentTypeHeader = contentType == null ? null : new MediaTypeHeaderValue(contentType);
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), type, new SimplePOCO())
|
||||
{
|
||||
DeclaredType = declaredType,
|
||||
Object = new SimplePOCO()
|
||||
ContentType = contentTypeHeader,
|
||||
};
|
||||
|
||||
// Act
|
||||
var canWrite = formatter.CanWriteResult(formatterContext, contentTypeHeader);
|
||||
var canWrite = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(canWrite);
|
||||
|
|
@ -70,56 +64,39 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
{
|
||||
// Arrange
|
||||
var formatter = new StreamOutputFormatter();
|
||||
var context = new OutputFormatterContext();
|
||||
var contentType = new MediaTypeHeaderValue("text/plain");
|
||||
var @object = type != null ? Activator.CreateInstance(type) : null;
|
||||
|
||||
context.Object = type != null ? Activator.CreateInstance(type) : null;
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), type, @object);
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(context, contentType);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
Assert.Null(context.SelectedContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CanWriteResult_SetsContentType()
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new StreamOutputFormatter();
|
||||
var contentType = new MediaTypeHeaderValue("text/plain");
|
||||
var context = new OutputFormatterContext();
|
||||
context.Object = new MemoryStream();
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(context, contentType);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
Assert.Same(contentType, context.SelectedContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DisablesResponseBuffering_IfBufferingFeatureAvailable()
|
||||
{
|
||||
// Arrange
|
||||
var expected = Encoding.UTF8.GetBytes("Test data");
|
||||
var formatter = new StreamOutputFormatter();
|
||||
|
||||
var expected = Encoding.UTF8.GetBytes("Test data");
|
||||
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var ms = new MemoryStream();
|
||||
httpContext.Response.Body = ms;
|
||||
var body = new MemoryStream();
|
||||
httpContext.Response.Body = body;
|
||||
|
||||
var bufferingFeature = new TestBufferingFeature();
|
||||
httpContext.Features.Set<IHttpBufferingFeature>(bufferingFeature);
|
||||
var context = new OutputFormatterContext();
|
||||
context.Object = new MemoryStream(expected);
|
||||
context.HttpContext = httpContext;
|
||||
|
||||
var context = new OutputFormatterWriteContext(httpContext, typeof(Stream), new MemoryStream(expected));
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, ms.ToArray());
|
||||
Assert.Equal(expected, body.ToArray());
|
||||
Assert.True(bufferingFeature.DisableResponseBufferingInvoked);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.IO;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -28,19 +29,18 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
[Theory]
|
||||
[MemberData(nameof(OutputFormatterContextValues))]
|
||||
public void CanWriteResult_ReturnsTrueForStringTypes(object value, bool useDeclaredTypeAsString, bool expectedCanWriteResult)
|
||||
public void CanWriteResult_ReturnsTrueForStringTypes(
|
||||
object value,
|
||||
bool useDeclaredTypeAsString,
|
||||
bool expectedCanWriteResult)
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new StringOutputFormatter();
|
||||
var typeToUse = useDeclaredTypeAsString ? typeof(string) : typeof(object);
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
{
|
||||
Object = value,
|
||||
DeclaredType = typeToUse
|
||||
};
|
||||
var type = useDeclaredTypeAsString ? typeof(string) : typeof(object);
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), type, value);
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(formatterContext, null);
|
||||
var result = formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedCanWriteResult, result);
|
||||
|
|
@ -55,20 +55,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
var response = new Mock<HttpResponse>();
|
||||
response.SetupProperty<long?>(o => o.ContentLength);
|
||||
response.SetupGet(r => r.Body).Returns(memoryStream);
|
||||
var mockHttpContext = new Mock<HttpContext>();
|
||||
mockHttpContext.Setup(o => o.Response).Returns(response.Object);
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.Setup(o => o.Response).Returns(response.Object);
|
||||
|
||||
var formatter = new StringOutputFormatter();
|
||||
var formatterContext = new OutputFormatterContext()
|
||||
{
|
||||
Object = null,
|
||||
DeclaredType = typeof(string),
|
||||
HttpContext = mockHttpContext.Object,
|
||||
SelectedEncoding = encoding
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(httpContext.Object, typeof(string), @object: null);
|
||||
|
||||
// Act
|
||||
await formatter.WriteResponseBodyAsync(formatterContext);
|
||||
await formatter.WriteResponseBodyAsync(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(0, memoryStream.Length);
|
||||
|
|
|
|||
|
|
@ -31,10 +31,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
new TestJsonOutputFormatter(), // This will be chosen based on the accept header
|
||||
};
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
context.HttpContext.Request.Headers[HeaderNames.Accept] = "application/json";
|
||||
|
||||
// Act
|
||||
|
|
@ -45,7 +42,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
// Assert
|
||||
Assert.Same(formatters[1], formatter);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/json"), context.SelectedContentType);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/json"), context.ContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -60,10 +57,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
new TestJsonOutputFormatter(), // This will be chosen based on the content type
|
||||
};
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
context.HttpContext.Request.Headers[HeaderNames.Accept] = "application/xml"; // This will not be used
|
||||
|
||||
// Act
|
||||
|
|
@ -74,7 +68,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
// Assert
|
||||
Assert.Same(formatters[1], formatter);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/json"), context.SelectedContentType);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/json"), context.ContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -88,10 +82,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
new TestXmlOutputFormatter(),
|
||||
};
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
context.HttpContext.Request.Headers[HeaderNames.Accept] = "application/xml"; // This will not be used
|
||||
|
||||
// Act
|
||||
|
|
@ -158,10 +149,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
new TestJsonOutputFormatter(),
|
||||
};
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
context.HttpContext.Request.Headers[HeaderNames.Accept] = acceptHeader;
|
||||
|
||||
// Act
|
||||
|
|
@ -172,7 +160,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
// Assert
|
||||
Assert.Same(formatters[1], formatter);
|
||||
Assert.Equal(new MediaTypeHeaderValue(expectedContentType), context.SelectedContentType);
|
||||
Assert.Equal(new MediaTypeHeaderValue(expectedContentType), context.ContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -188,10 +176,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
new TestXmlOutputFormatter(),
|
||||
};
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
|
||||
// Act
|
||||
var formatter = executor.SelectFormatter(
|
||||
|
|
@ -201,7 +186,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
// Assert
|
||||
Assert.Same(formatters[1], formatter);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/json"), context.SelectedContentType);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/json"), context.ContentType);
|
||||
Assert.Null(context.FailedContentNegotiation);
|
||||
}
|
||||
|
||||
|
|
@ -217,10 +202,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
new TestJsonOutputFormatter(),
|
||||
};
|
||||
|
||||
var context = new OutputFormatterContext()
|
||||
{
|
||||
HttpContext = new DefaultHttpContext(),
|
||||
};
|
||||
var context = new OutputFormatterWriteContext(new DefaultHttpContext(), objectType: null, @object: null);
|
||||
context.HttpContext.Request.Headers[HeaderNames.Accept] = "text/custom, application/custom";
|
||||
|
||||
// Act
|
||||
|
|
@ -231,7 +213,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
// Assert
|
||||
Assert.Same(formatters[0], formatter);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/xml"), context.SelectedContentType);
|
||||
Assert.Equal(new MediaTypeHeaderValue("application/xml"), context.ContentType);
|
||||
Assert.True(context.FailedContentNegotiation);
|
||||
}
|
||||
|
||||
|
|
@ -437,12 +419,12 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
|
||||
private class CannotWriteFormatter : IOutputFormatter
|
||||
{
|
||||
public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public virtual bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual Task WriteAsync(OutputFormatterContext context)
|
||||
public virtual Task WriteAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
@ -458,7 +440,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
SupportedEncodings.Add(Encoding.UTF8);
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
|
@ -474,7 +456,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
SupportedEncodings.Add(Encoding.UTF8);
|
||||
}
|
||||
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
|
@ -491,7 +473,7 @@ namespace Microsoft.AspNet.Mvc.Infrastructure
|
|||
}
|
||||
|
||||
public new IOutputFormatter SelectFormatter(
|
||||
OutputFormatterContext formatterContext,
|
||||
OutputFormatterWriteContext formatterContext,
|
||||
IList<MediaTypeHeaderValue> contentTypes,
|
||||
IEnumerable<IOutputFormatter> formatters)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -74,12 +74,12 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
private class NoOpOutputFormatter : IOutputFormatter
|
||||
{
|
||||
public bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public Task WriteAsync(OutputFormatterContext context)
|
||||
public Task WriteAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,19 +165,20 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
// Arrange
|
||||
var formatter = new JsonOutputFormatter();
|
||||
var formattedContent = "\"" + content + "\"";
|
||||
var mediaType = string.Format("application/json; charset={0}", encodingAsString);
|
||||
var mediaType = MediaTypeHeaderValue.Parse(string.Format("application/json; charset={0}", encodingAsString));
|
||||
var encoding = CreateOrGetSupportedEncoding(formatter, encodingAsString, isDefaultEncoding);
|
||||
var expectedData = encoding.GetBytes(formattedContent);
|
||||
|
||||
|
||||
var body = new MemoryStream();
|
||||
var actionContext = GetActionContext(MediaTypeHeaderValue.Parse(mediaType), body);
|
||||
var outputFormatterContext = new OutputFormatterContext
|
||||
var actionContext = GetActionContext(mediaType, body);
|
||||
|
||||
var outputFormatterContext = new OutputFormatterWriteContext(
|
||||
actionContext.HttpContext,
|
||||
typeof(string),
|
||||
content)
|
||||
{
|
||||
Object = content,
|
||||
DeclaredType = typeof(string),
|
||||
HttpContext = actionContext.HttpContext,
|
||||
SelectedEncoding = encoding
|
||||
ContentType = mediaType,
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -208,7 +209,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
return encoding;
|
||||
}
|
||||
|
||||
private static OutputFormatterContext GetOutputFormatterContext(
|
||||
private static OutputFormatterWriteContext GetOutputFormatterContext(
|
||||
object outputValue,
|
||||
Type outputType,
|
||||
string contentType = "application/xml; charset=utf-8",
|
||||
|
|
@ -217,12 +218,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType);
|
||||
|
||||
var actionContext = GetActionContext(mediaTypeHeaderValue, responseStream);
|
||||
return new OutputFormatterContext
|
||||
return new OutputFormatterWriteContext(actionContext.HttpContext, outputType, outputValue)
|
||||
{
|
||||
Object = outputValue,
|
||||
DeclaredType = outputType,
|
||||
HttpContext = actionContext.HttpContext,
|
||||
SelectedEncoding = Encoding.GetEncoding(mediaTypeHeaderValue.Charset)
|
||||
ContentType = mediaTypeHeaderValue,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
{
|
||||
// Arrange
|
||||
var formatter = new XmlDataContractSerializerOutputFormatter();
|
||||
var outputFormatterContext = GetOutputFormatterContext(input, typeof(object));
|
||||
var outputFormatterContext = GetOutputFormatterContext(input, input.GetType());
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(outputFormatterContext);
|
||||
|
|
@ -121,11 +121,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
// Arrange
|
||||
var input = new DummyClass { SampleInt = 10 };
|
||||
var formatter = new TestXmlDataContractSerializerOutputFormatter();
|
||||
|
||||
var context = GetOutputFormatterContext(input, typeof(DummyClass));
|
||||
context.ContentType = MediaTypeHeaderValue.Parse("application/xml");
|
||||
|
||||
// Act
|
||||
formatter.CanWriteResult(context, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
formatter.CanWriteResult(context, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
formatter.CanWriteResult(context);
|
||||
formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, formatter.createSerializerCalledCount);
|
||||
|
|
@ -363,9 +365,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
{
|
||||
yield return new object[] { null, typeof(string), true };
|
||||
yield return new object[] { null, null, false };
|
||||
yield return new object[] { new DummyClass { SampleInt = 5 }, null, true };
|
||||
yield return new object[] { new DummyClass { SampleInt = 5 }, typeof(object), true };
|
||||
yield return new object[] { null, typeof(object), true };
|
||||
yield return new object[] { new DummyClass { SampleInt = 5 }, typeof(DummyClass), true };
|
||||
yield return new object[] {
|
||||
new Dictionary<string, string> { { "Hello", "world" } }, typeof(object), true };
|
||||
yield return new object[] {
|
||||
|
|
@ -382,9 +382,10 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
// Arrange
|
||||
var formatter = new XmlDataContractSerializerOutputFormatter();
|
||||
var outputFormatterContext = GetOutputFormatterContext(input, declaredType);
|
||||
outputFormatterContext.ContentType = MediaTypeHeaderValue.Parse("application/xml");
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(outputFormatterContext, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
var result = formatter.CanWriteResult(outputFormatterContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedOutput, result);
|
||||
|
|
@ -394,12 +395,9 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] { typeof(DummyClass), typeof(DummyClass), "application/xml" };
|
||||
yield return new object[] { typeof(DummyClass), typeof(object), "application/xml" };
|
||||
yield return new object[] { null, typeof(DummyClass), "application/xml" };
|
||||
yield return new object[] { typeof(DummyClass), null, "application/xml" };
|
||||
yield return new object[] { typeof(object), null, "application/xml" };
|
||||
yield return new object[] { null, null, null };
|
||||
yield return new object[] { typeof(DummyClass), "application/xml" };
|
||||
yield return new object[] { typeof(object), "application/xml" };
|
||||
yield return new object[] { null, null };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -407,17 +405,15 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
// Mono issue - https://github.com/aspnet/External/issues/18
|
||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
||||
[MemberData(nameof(TypesForGetSupportedContentTypes))]
|
||||
public void GetSupportedContentTypes_ReturnsSupportedTypes(
|
||||
Type declaredType,
|
||||
Type runtimeType,
|
||||
object expectedOutput)
|
||||
public void GetSupportedContentTypes_ReturnsSupportedTypes(Type type, object expectedOutput)
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new XmlDataContractSerializerOutputFormatter();
|
||||
|
||||
// Act
|
||||
var result = formatter.GetSupportedContentTypes(
|
||||
declaredType, runtimeType, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
MediaTypeHeaderValue.Parse("application/xml"),
|
||||
type);
|
||||
|
||||
// Assert
|
||||
if (expectedOutput != null)
|
||||
|
|
@ -598,17 +594,12 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
XmlAssert.Equal(expectedOutput, content);
|
||||
}
|
||||
|
||||
private OutputFormatterContext GetOutputFormatterContext(
|
||||
private OutputFormatterWriteContext GetOutputFormatterContext(
|
||||
object outputValue,
|
||||
Type outputType,
|
||||
string contentType = "application/xml; charset=utf-8")
|
||||
{
|
||||
return new OutputFormatterContext
|
||||
{
|
||||
Object = outputValue,
|
||||
DeclaredType = outputType,
|
||||
HttpContext = GetHttpContext(contentType)
|
||||
};
|
||||
return new OutputFormatterWriteContext(GetHttpContext(contentType), outputType, outputValue);
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(string contentType)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
{
|
||||
// Arrange
|
||||
var formatter = new XmlSerializerOutputFormatter();
|
||||
var outputFormatterContext = GetOutputFormatterContext(input, typeof(object));
|
||||
var outputFormatterContext = GetOutputFormatterContext(input, input.GetType());
|
||||
|
||||
// Act
|
||||
await formatter.WriteAsync(outputFormatterContext);
|
||||
|
|
@ -74,11 +74,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
// Arrange
|
||||
var input = new DummyClass { SampleInt = 10 };
|
||||
var formatter = new TestXmlSerializerOutputFormatter();
|
||||
|
||||
var context = GetOutputFormatterContext(input, typeof(DummyClass));
|
||||
context.ContentType = MediaTypeHeaderValue.Parse("application/xml");
|
||||
|
||||
// Act
|
||||
formatter.CanWriteResult(context, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
formatter.CanWriteResult(context, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
formatter.CanWriteResult(context);
|
||||
formatter.CanWriteResult(context);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, formatter.createSerializerCalledCount);
|
||||
|
|
@ -280,11 +282,8 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
{
|
||||
yield return new object[] { null, typeof(string), true };
|
||||
yield return new object[] { null, null, false };
|
||||
yield return new object[] { new DummyClass { SampleInt = 5 }, null, true };
|
||||
yield return new object[] { new DummyClass { SampleInt = 5 }, typeof(object), true };
|
||||
yield return new object[] { new DummyClass { SampleInt = 5 }, typeof(DummyClass), true };
|
||||
yield return new object[] { null, typeof(object), true };
|
||||
yield return new object[] {
|
||||
new Dictionary<string, string> { { "Hello", "world" } }, typeof(object), false };
|
||||
yield return new object[] {
|
||||
new Dictionary<string, string> { { "Hello", "world" } }, typeof(Dictionary<string,string>), false };
|
||||
yield return new object[] {
|
||||
|
|
@ -301,9 +300,10 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
// Arrange
|
||||
var formatter = new XmlSerializerOutputFormatter();
|
||||
var outputFormatterContext = GetOutputFormatterContext(input, declaredType);
|
||||
outputFormatterContext.ContentType = MediaTypeHeaderValue.Parse("application/xml");
|
||||
|
||||
// Act
|
||||
var result = formatter.CanWriteResult(outputFormatterContext, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
var result = formatter.CanWriteResult(outputFormatterContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedOutput, result);
|
||||
|
|
@ -328,25 +328,21 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] { typeof(DummyClass), typeof(DummyClass), "application/xml" };
|
||||
yield return new object[] { typeof(DummyClass), typeof(object), "application/xml" };
|
||||
yield return new object[] { null, typeof(DummyClass), "application/xml" };
|
||||
yield return new object[] { typeof(DummyClass), null, "application/xml" };
|
||||
yield return new object[] { typeof(object), null, "application/xml" };
|
||||
yield return new object[] { null, null, null };
|
||||
yield return new object[] { typeof(DummyClass), "application/xml" };
|
||||
yield return new object[] { typeof(object), "application/xml" };
|
||||
yield return new object[] { null, null };
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TypesForGetSupportedContentTypes))]
|
||||
public void XmlSerializer_GetSupportedContentTypes_Returns_SupportedTypes(Type declaredType, Type runtimeType, object expectedOutput)
|
||||
public void XmlSerializer_GetSupportedContentTypes_Returns_SupportedTypes(Type type, object expectedOutput)
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new XmlSerializerOutputFormatter();
|
||||
|
||||
// Act
|
||||
var result = formatter.GetSupportedContentTypes(
|
||||
declaredType, runtimeType, MediaTypeHeaderValue.Parse("application/xml"));
|
||||
var result = formatter.GetSupportedContentTypes(MediaTypeHeaderValue.Parse("application/xml"), type);
|
||||
|
||||
// Assert
|
||||
if (expectedOutput != null)
|
||||
|
|
@ -359,17 +355,12 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
|
|||
}
|
||||
}
|
||||
|
||||
private OutputFormatterContext GetOutputFormatterContext(
|
||||
private OutputFormatterWriteContext GetOutputFormatterContext(
|
||||
object outputValue,
|
||||
Type outputType,
|
||||
string contentType = "application/xml; charset=utf-8")
|
||||
{
|
||||
return new OutputFormatterContext
|
||||
{
|
||||
Object = outputValue,
|
||||
DeclaredType = outputType,
|
||||
HttpContext = GetHttpContext(contentType)
|
||||
};
|
||||
return new OutputFormatterWriteContext(GetHttpContext(contentType), outputType, outputValue);
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(string contentType)
|
||||
|
|
|
|||
|
|
@ -146,17 +146,12 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShimTest
|
|||
Assert.NotNull(httpContext.Response.ContentLength);
|
||||
}
|
||||
|
||||
private OutputFormatterContext GetOutputFormatterContext(
|
||||
private OutputFormatterWriteContext GetOutputFormatterContext(
|
||||
object outputValue,
|
||||
Type outputType,
|
||||
HttpContext httpContext)
|
||||
{
|
||||
return new OutputFormatterContext
|
||||
{
|
||||
Object = outputValue,
|
||||
DeclaredType = outputType,
|
||||
HttpContext = httpContext,
|
||||
};
|
||||
return new OutputFormatterWriteContext(httpContext, outputType, outputValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ namespace ContentNegotiationWebSite
|
|||
SupportedEncodings.Add(Encoding.GetEncoding("utf-8"));
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
if (base.CanWriteResult(context, contentType))
|
||||
if (base.CanWriteResult(context))
|
||||
{
|
||||
var actionReturnString = context.Object as string;
|
||||
if (actionReturnString != null)
|
||||
|
|
@ -33,7 +33,7 @@ namespace ContentNegotiationWebSite
|
|||
return false;
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
response.ContentType = ContentType + ";charset=utf-8";
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ namespace ContentNegotiationWebSite
|
|||
SupportedEncodings.Add(Encoding.GetEncoding("utf-8"));
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
if (base.CanWriteResult(context, contentType))
|
||||
if (base.CanWriteResult(context))
|
||||
{
|
||||
var actionReturnString = context.Object as string;
|
||||
if (actionReturnString != null)
|
||||
|
|
@ -31,7 +31,7 @@ namespace ContentNegotiationWebSite
|
|||
return false;
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
response.ContentType = "text/plain;charset=utf-8";
|
||||
|
|
|
|||
|
|
@ -23,12 +23,12 @@ namespace ContentNegotiationWebSite
|
|||
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/vcard;version=v3.0"));
|
||||
}
|
||||
|
||||
protected override bool CanWriteType(Type declaredType, Type runtimeType)
|
||||
protected override bool CanWriteType(Type type)
|
||||
{
|
||||
return typeof(Contact).GetTypeInfo().IsAssignableFrom(runtimeType.GetTypeInfo());
|
||||
return typeof(Contact).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo());
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var contact = (Contact)context.Object;
|
||||
|
||||
|
|
@ -38,7 +38,9 @@ namespace ContentNegotiationWebSite
|
|||
builder.AppendLine();
|
||||
builder.AppendLine("END:VCARD");
|
||||
|
||||
await context.HttpContext.Response.WriteAsync(builder.ToString(), context.SelectedEncoding);
|
||||
await context.HttpContext.Response.WriteAsync(
|
||||
builder.ToString(),
|
||||
context.ContentType?.Encoding ?? Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,12 +24,12 @@ namespace ContentNegotiationWebSite
|
|||
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/vcard;version=v4.0"));
|
||||
}
|
||||
|
||||
protected override bool CanWriteType(Type declaredType, Type runtimeType)
|
||||
protected override bool CanWriteType(Type type)
|
||||
{
|
||||
return typeof(Contact).GetTypeInfo().IsAssignableFrom(runtimeType.GetTypeInfo());
|
||||
return typeof(Contact).GetTypeInfo().IsAssignableFrom(type.GetTypeInfo());
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var contact = (Contact)context.Object;
|
||||
|
||||
|
|
@ -41,7 +41,9 @@ namespace ContentNegotiationWebSite
|
|||
builder.AppendLine();
|
||||
builder.AppendLine("END:VCARD");
|
||||
|
||||
await context.HttpContext.Response.WriteAsync(builder.ToString(), context.SelectedEncoding);
|
||||
await context.HttpContext.Response.WriteAsync(
|
||||
builder.ToString(),
|
||||
context.ContentType?.Encoding ?? Encoding.UTF8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.Formatters;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
|
|
@ -21,22 +20,20 @@ namespace FormatFilterWebSite
|
|||
SupportedEncodings.Add(Encoding.GetEncoding("utf-8"));
|
||||
}
|
||||
|
||||
public override bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
public override bool CanWriteResult(OutputFormatterCanWriteContext context)
|
||||
{
|
||||
if (base.CanWriteResult(context, contentType))
|
||||
if (base.CanWriteResult(context))
|
||||
{
|
||||
var actionReturn = context.Object as Product;
|
||||
if (actionReturn != null)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
context.SelectedContentType = contentType;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||
public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||
{
|
||||
var response = context.HttpContext.Response;
|
||||
await response.WriteAsync(context.Object.ToString());
|
||||
|
|
|
|||
Loading…
Reference in New Issue