Fix #2330 - Reimagine *FormatterContext
This change simplifies InputFormatterContext/OutputFormatterContext by swapping ActionContext for HttpContext. This change is important especially for InputFormatterContext as it decouples ModelState from ActionContext - allowing us to fix a related bug where the _wrong_ ModelState can be passed in for a TryUpdateModel operation.
This commit is contained in:
parent
fcf7b15c64
commit
39fe063aee
|
|
@ -2,33 +2,51 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents information used by an input formatter for
|
/// A context object used by an input formatter for deserializing the request body into an object.
|
||||||
/// deserializing the request body into an object.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class InputFormatterContext
|
public class InputFormatterContext
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of <see cref="InputFormatterContext"/>.
|
/// Creates a new instance of <see cref="InputFormatterContext"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public InputFormatterContext([NotNull] ActionContext actionContext,
|
/// <param name="httpContext">
|
||||||
[NotNull] Type modelType)
|
/// The <see cref="Http.HttpContext"/> for the current operation.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="modelState">
|
||||||
|
/// The <see cref="ModelStateDictionary"/> for recording errors.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="modelType">
|
||||||
|
/// The <see cref="Type"/> of the model to deserialize.
|
||||||
|
/// </param>
|
||||||
|
public InputFormatterContext(
|
||||||
|
[NotNull] HttpContext httpContext,
|
||||||
|
[NotNull] ModelStateDictionary modelState,
|
||||||
|
[NotNull] Type modelType)
|
||||||
{
|
{
|
||||||
ActionContext = actionContext;
|
HttpContext = httpContext;
|
||||||
|
ModelState = modelState;
|
||||||
ModelType = modelType;
|
ModelType = modelType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action context associated with the current call.
|
/// Gets the <see cref="Http.HttpContext"/> associated with the current operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ActionContext ActionContext { get; private set; }
|
public HttpContext HttpContext { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the expected type of the model represented by the request body.
|
/// Gets the <see cref="ModelStateDictionary"/> associated with the current operation.
|
||||||
|
/// </summary>
|
||||||
|
public ModelStateDictionary ModelState { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the expected <see cref="Type"/> of the model represented by the request body.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Type ModelType { get; private set; }
|
public Type ModelType { get; private set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
|
@ -24,9 +25,9 @@ namespace Microsoft.AspNet.Mvc
|
||||||
public Type DeclaredType { get; set; }
|
public Type DeclaredType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Action context associated with the current call.
|
/// Gets or sets the <see cref="HttpContext"/> context associated with the current operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ActionContext ActionContext { get; set; }
|
public HttpContext HttpContext { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The encoding which is chosen by the selected formatter.
|
/// The encoding which is chosen by the selected formatter.
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
var formatterContext = new OutputFormatterContext()
|
var formatterContext = new OutputFormatterContext()
|
||||||
{
|
{
|
||||||
ActionContext = context,
|
HttpContext = context.HttpContext,
|
||||||
DeclaredType = objectResult.DeclaredType,
|
DeclaredType = objectResult.DeclaredType,
|
||||||
Object = Value,
|
Object = Value,
|
||||||
};
|
};
|
||||||
|
|
@ -125,7 +125,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
// If no formatter was provided, then run Conneg with the formatters configured in options.
|
// If no formatter was provided, then run Conneg with the formatters configured in options.
|
||||||
var formatters = formatterContext
|
var formatters = formatterContext
|
||||||
.ActionContext
|
|
||||||
.HttpContext
|
.HttpContext
|
||||||
.RequestServices
|
.RequestServices
|
||||||
.GetRequiredService<IOptions<MvcOptions>>()
|
.GetRequiredService<IOptions<MvcOptions>>()
|
||||||
|
|
@ -140,7 +139,6 @@ namespace Microsoft.AspNet.Mvc
|
||||||
// If the available user-configured formatters can't write this type, then fall back to the
|
// If the available user-configured formatters can't write this type, then fall back to the
|
||||||
// 'global' one.
|
// 'global' one.
|
||||||
formatter = formatterContext
|
formatter = formatterContext
|
||||||
.ActionContext
|
|
||||||
.HttpContext
|
.HttpContext
|
||||||
.RequestServices
|
.RequestServices
|
||||||
.GetRequiredService<JsonOutputFormatter>();
|
.GetRequiredService<JsonOutputFormatter>();
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var formatterContext = new OutputFormatterContext()
|
var formatterContext = new OutputFormatterContext()
|
||||||
{
|
{
|
||||||
DeclaredType = DeclaredType,
|
DeclaredType = DeclaredType,
|
||||||
ActionContext = context,
|
HttpContext = context.HttpContext,
|
||||||
Object = Value,
|
Object = Value,
|
||||||
StatusCode = StatusCode
|
StatusCode = StatusCode
|
||||||
};
|
};
|
||||||
|
|
@ -83,8 +83,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
OutputFormatterContext formatterContext,
|
OutputFormatterContext formatterContext,
|
||||||
IEnumerable<IOutputFormatter> formatters)
|
IEnumerable<IOutputFormatter> formatters)
|
||||||
{
|
{
|
||||||
var logger = formatterContext.ActionContext.HttpContext.RequestServices
|
var logger = formatterContext.HttpContext.RequestServices.GetRequiredService<ILogger<ObjectResult>>();
|
||||||
.GetRequiredService<ILogger<ObjectResult>>();
|
|
||||||
|
|
||||||
// Check if any content-type was explicitly set (for example, via ProducesAttribute
|
// Check if any content-type was explicitly set (for example, via ProducesAttribute
|
||||||
// or Url path extension mapping). If yes, then ignore content-negotiation and use this content-type.
|
// or Url path extension mapping). If yes, then ignore content-negotiation and use this content-type.
|
||||||
|
|
@ -108,7 +107,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
// which can write the type.
|
// which can write the type.
|
||||||
MediaTypeHeaderValue requestContentType = null;
|
MediaTypeHeaderValue requestContentType = null;
|
||||||
MediaTypeHeaderValue.TryParse(
|
MediaTypeHeaderValue.TryParse(
|
||||||
formatterContext.ActionContext.HttpContext.Request.ContentType,
|
formatterContext.HttpContext.Request.ContentType,
|
||||||
out requestContentType);
|
out requestContentType);
|
||||||
if (!sortedAcceptHeaderMediaTypes.Any() && requestContentType == null)
|
if (!sortedAcceptHeaderMediaTypes.Any() && requestContentType == null)
|
||||||
{
|
{
|
||||||
|
|
@ -240,17 +239,18 @@ namespace Microsoft.AspNet.Mvc
|
||||||
private IEnumerable<MediaTypeHeaderValue> GetSortedAcceptHeaderMediaTypes(
|
private IEnumerable<MediaTypeHeaderValue> GetSortedAcceptHeaderMediaTypes(
|
||||||
OutputFormatterContext formatterContext)
|
OutputFormatterContext formatterContext)
|
||||||
{
|
{
|
||||||
var request = formatterContext.ActionContext.HttpContext.Request;
|
var request = formatterContext.HttpContext.Request;
|
||||||
var incomingAcceptHeaderMediaTypes = request.GetTypedHeaders().Accept ?? new MediaTypeHeaderValue[] { };
|
var incomingAcceptHeaderMediaTypes = request.GetTypedHeaders().Accept ?? new MediaTypeHeaderValue[] { };
|
||||||
|
|
||||||
// By default we want to ignore considering accept headers for content negotiation when
|
// By default we want to ignore considering accept headers for content negotiation when
|
||||||
// they have a media type like */* in them. Browsers typically have these media types.
|
// they have a media type like */* in them. Browsers typically have these media types.
|
||||||
// In these cases we would want the first formatter in the list of output formatters to
|
// In these cases we would want the first formatter in the list of output formatters to
|
||||||
// write the response. This default behavior can be changed through options, so checking here.
|
// write the response. This default behavior can be changed through options, so checking here.
|
||||||
var options = formatterContext.ActionContext.HttpContext
|
var options = formatterContext
|
||||||
.RequestServices
|
.HttpContext
|
||||||
.GetRequiredService<IOptions<MvcOptions>>()
|
.RequestServices
|
||||||
.Options;
|
.GetRequiredService<IOptions<MvcOptions>>()
|
||||||
|
.Options;
|
||||||
|
|
||||||
var respectAcceptHeader = true;
|
var respectAcceptHeader = true;
|
||||||
if (options.RespectBrowserAcceptHeader == false
|
if (options.RespectBrowserAcceptHeader == false
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
public Task WriteAsync(OutputFormatterContext context)
|
public Task WriteAsync(OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
response.ContentLength = 0;
|
response.ContentLength = 0;
|
||||||
response.StatusCode = context.StatusCode ?? StatusCodes.Status204NoContent;
|
response.StatusCode = context.StatusCode ?? StatusCodes.Status204NoContent;
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task WriteAsync(OutputFormatterContext context)
|
public Task WriteAsync(OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
response.StatusCode = StatusCodes.Status406NotAcceptable;
|
response.StatusCode = StatusCodes.Status406NotAcceptable;
|
||||||
return Task.FromResult(true);
|
return Task.FromResult(true);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var contentType = context.ActionContext.HttpContext.Request.ContentType;
|
var contentType = context.HttpContext.Request.ContentType;
|
||||||
MediaTypeHeaderValue requestContentType;
|
MediaTypeHeaderValue requestContentType;
|
||||||
if (!MediaTypeHeaderValue.TryParse(contentType, out requestContentType))
|
if (!MediaTypeHeaderValue.TryParse(contentType, out requestContentType))
|
||||||
{
|
{
|
||||||
|
|
@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual async Task<object> ReadAsync(InputFormatterContext context)
|
public virtual async Task<object> ReadAsync(InputFormatterContext context)
|
||||||
{
|
{
|
||||||
var request = context.ActionContext.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
if (request.ContentLength == 0)
|
if (request.ContentLength == 0)
|
||||||
{
|
{
|
||||||
return GetDefaultValueForType(context.ModelType);
|
return GetDefaultValueForType(context.ModelType);
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
public override Task<object> ReadRequestBodyAsync([NotNull] InputFormatterContext context)
|
public override Task<object> ReadRequestBodyAsync([NotNull] InputFormatterContext context)
|
||||||
{
|
{
|
||||||
var type = context.ModelType;
|
var type = context.ModelType;
|
||||||
var request = context.ActionContext.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
MediaTypeHeaderValue requestContentType = null;
|
MediaTypeHeaderValue requestContentType = null;
|
||||||
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
|
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
errorHandler = (sender, e) =>
|
errorHandler = (sender, e) =>
|
||||||
{
|
{
|
||||||
var exception = e.ErrorContext.Error;
|
var exception = e.ErrorContext.Error;
|
||||||
context.ActionContext.ModelState.TryAddModelError(e.ErrorContext.Path, e.ErrorContext.Error);
|
context.ModelState.TryAddModelError(e.ErrorContext.Path, e.ErrorContext.Error);
|
||||||
|
|
||||||
// Error must always be marked as handled
|
// Error must always be marked as handled
|
||||||
// Failure to do so can cause the exception to be rethrown at every recursive level and
|
// Failure to do so can cause the exception to be rethrown at every recursive level and
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
|
|
||||||
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
var selectedEncoding = context.SelectedEncoding;
|
var selectedEncoding = context.SelectedEncoding;
|
||||||
|
|
||||||
using (var writer = new HttpResponseStreamWriter(response.Body, selectedEncoding))
|
using (var writer = new HttpResponseStreamWriter(response.Body, selectedEncoding))
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
/// <returns>The <see cref="Encoding"/> to use when reading the request or writing the response.</returns>
|
/// <returns>The <see cref="Encoding"/> to use when reading the request or writing the response.</returns>
|
||||||
public virtual Encoding SelectCharacterEncoding([NotNull] OutputFormatterContext context)
|
public virtual Encoding SelectCharacterEncoding([NotNull] OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var request = context.ActionContext.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
var encoding = MatchAcceptCharacterEncoding(request.GetTypedHeaders().AcceptCharset);
|
var encoding = MatchAcceptCharacterEncoding(request.GetTypedHeaders().AcceptCharset);
|
||||||
if (encoding == null)
|
if (encoding == null)
|
||||||
{
|
{
|
||||||
|
|
@ -195,7 +195,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
selectedMediaType.Charset = selectedEncoding.WebName;
|
selectedMediaType.Charset = selectedEncoding.WebName;
|
||||||
|
|
||||||
context.SelectedContentType = context.SelectedContentType ?? selectedMediaType;
|
context.SelectedContentType = context.SelectedContentType ?? selectedMediaType;
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
response.ContentType = selectedMediaType.ToString();
|
response.ContentType = selectedMediaType.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
using (var valueAsStream = ((Stream)context.Object))
|
using (var valueAsStream = ((Stream)context.Object))
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
|
|
||||||
if (context.SelectedContentType != null)
|
if (context.SelectedContentType != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
|
|
||||||
await response.WriteAsync(valueAsString, context.SelectedEncoding);
|
await response.WriteAsync(valueAsString, context.SelectedEncoding);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
|
@ -26,14 +25,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected async override Task<ModelBindingResult> BindModelCoreAsync([NotNull] ModelBindingContext bindingContext)
|
protected async override Task<ModelBindingResult> BindModelCoreAsync(
|
||||||
|
[NotNull] ModelBindingContext bindingContext)
|
||||||
{
|
{
|
||||||
var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices;
|
var requestServices = bindingContext.OperationBindingContext.HttpContext.RequestServices;
|
||||||
|
|
||||||
var actionContext = requestServices.GetRequiredService<IScopedInstance<ActionContext>>().Value;
|
var httpContext = bindingContext.OperationBindingContext.HttpContext;
|
||||||
var formatters = requestServices.GetRequiredService<IScopedInstance<ActionBindingContext>>().Value.InputFormatters;
|
var formatters = requestServices
|
||||||
|
.GetRequiredService<IScopedInstance<ActionBindingContext>>().Value.InputFormatters;
|
||||||
|
|
||||||
var formatterContext = new InputFormatterContext(actionContext, bindingContext.ModelType);
|
var formatterContext = new InputFormatterContext(
|
||||||
|
httpContext,
|
||||||
|
bindingContext.ModelState,
|
||||||
|
bindingContext.ModelType);
|
||||||
var formatter = formatters.FirstOrDefault(f => f.CanRead(formatterContext));
|
var formatter = formatters.FirstOrDefault(f => f.CanRead(formatterContext));
|
||||||
|
|
||||||
if (formatter == null)
|
if (formatter == null)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
||||||
|
|
||||||
public async Task WriteAsync(OutputFormatterContext context)
|
public async Task WriteAsync(OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
|
|
||||||
var responseMessage = context.Object as HttpResponseMessage;
|
var responseMessage = context.Object as HttpResponseMessage;
|
||||||
if (responseMessage == null)
|
if (responseMessage == null)
|
||||||
|
|
@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
||||||
{
|
{
|
||||||
response.StatusCode = (int)responseMessage.StatusCode;
|
response.StatusCode = (int)responseMessage.StatusCode;
|
||||||
|
|
||||||
var responseFeature = context.ActionContext.HttpContext.GetFeature<IHttpResponseFeature>();
|
var responseFeature = context.HttpContext.GetFeature<IHttpResponseFeature>();
|
||||||
if (responseFeature != null)
|
if (responseFeature != null)
|
||||||
{
|
{
|
||||||
responseFeature.ReasonPhrase = responseMessage.ReasonPhrase;
|
responseFeature.ReasonPhrase = responseMessage.ReasonPhrase;
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
/// <returns>Task which reads the input.</returns>
|
/// <returns>Task which reads the input.</returns>
|
||||||
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
|
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
|
||||||
{
|
{
|
||||||
var request = context.ActionContext.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
|
|
||||||
MediaTypeHeaderValue requestContentType;
|
MediaTypeHeaderValue requestContentType;
|
||||||
MediaTypeHeaderValue.TryParse(request.ContentType , out requestContentType);
|
MediaTypeHeaderValue.TryParse(request.ContentType , out requestContentType);
|
||||||
|
|
@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
_dataAnnotationRequiredAttributeValidation.Validate(
|
_dataAnnotationRequiredAttributeValidation.Validate(
|
||||||
type,
|
type,
|
||||||
context.ActionContext.ModelState);
|
context.ModelState);
|
||||||
|
|
||||||
var serializer = GetCachedSerializer(type);
|
var serializer = GetCachedSerializer(type);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
var tempWriterSettings = WriterSettings.Clone();
|
var tempWriterSettings = WriterSettings.Clone();
|
||||||
tempWriterSettings.Encoding = context.SelectedEncoding;
|
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||||
|
|
||||||
var innerStream = context.ActionContext.HttpContext.Response.Body;
|
var innerStream = context.HttpContext.Response.Body;
|
||||||
|
|
||||||
using (var outputStream = new NonDisposableStream(innerStream))
|
using (var outputStream = new NonDisposableStream(innerStream))
|
||||||
using (var xmlWriter = CreateXmlWriter(outputStream, tempWriterSettings))
|
using (var xmlWriter = CreateXmlWriter(outputStream, tempWriterSettings))
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
/// <returns>Task which reads the input.</returns>
|
/// <returns>Task which reads the input.</returns>
|
||||||
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
|
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
|
||||||
{
|
{
|
||||||
var request = context.ActionContext.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
|
|
||||||
MediaTypeHeaderValue requestContentType;
|
MediaTypeHeaderValue requestContentType;
|
||||||
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
|
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
|
||||||
|
|
|
||||||
|
|
@ -139,12 +139,12 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
|
public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
|
|
||||||
var tempWriterSettings = WriterSettings.Clone();
|
var tempWriterSettings = WriterSettings.Clone();
|
||||||
tempWriterSettings.Encoding = context.SelectedEncoding;
|
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||||
|
|
||||||
var innerStream = context.ActionContext.HttpContext.Response.Body;
|
var innerStream = context.HttpContext.Response.Body;
|
||||||
|
|
||||||
using (var outputStream = new NonDisposableStream(innerStream))
|
using (var outputStream = new NonDisposableStream(innerStream))
|
||||||
using (var xmlWriter = CreateXmlWriter(outputStream, tempWriterSettings))
|
using (var xmlWriter = CreateXmlWriter(outputStream, tempWriterSettings))
|
||||||
|
|
|
||||||
|
|
@ -357,7 +357,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
|
||||||
|
|
||||||
var context = new OutputFormatterContext()
|
var context = new OutputFormatterContext()
|
||||||
{
|
{
|
||||||
ActionContext = actionContext,
|
HttpContext = actionContext.HttpContext,
|
||||||
Object = input,
|
Object = input,
|
||||||
DeclaredType = typeof(string)
|
DeclaredType = typeof(string)
|
||||||
};
|
};
|
||||||
|
|
@ -530,7 +530,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
|
||||||
new ActionDescriptor());
|
new ActionDescriptor());
|
||||||
var formatterContext = new OutputFormatterContext()
|
var formatterContext = new OutputFormatterContext()
|
||||||
{
|
{
|
||||||
ActionContext = tempActionContext,
|
HttpContext = tempActionContext.HttpContext,
|
||||||
Object = nonStringValue,
|
Object = nonStringValue,
|
||||||
DeclaredType = nonStringValue.GetType()
|
DeclaredType = nonStringValue.GetType()
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var formatter = new JsonInputFormatter();
|
var formatter = new JsonInputFormatter();
|
||||||
var contentBytes = Encoding.UTF8.GetBytes("content");
|
var contentBytes = Encoding.UTF8.GetBytes("content");
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
|
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
|
||||||
var formatterContext = new InputFormatterContext(actionContext, typeof(string));
|
var formatterContext = new InputFormatterContext(httpContext, new ModelStateDictionary(), typeof(string));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = formatter.CanRead(formatterContext);
|
var result = formatter.CanRead(formatterContext);
|
||||||
|
|
@ -80,8 +80,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var formatter = new JsonInputFormatter();
|
var formatter = new JsonInputFormatter();
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
var context = new InputFormatterContext(actionContext, type);
|
var context = new InputFormatterContext(httpContext, new ModelStateDictionary(), type);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
@ -98,9 +98,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var formatter = new JsonInputFormatter();
|
var formatter = new JsonInputFormatter();
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(User));
|
var context = new InputFormatterContext(httpContext, new ModelStateDictionary(), typeof(User));
|
||||||
var context = new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
@ -119,16 +118,18 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var formatter = new JsonInputFormatter();
|
var formatter = new JsonInputFormatter();
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var modelState = new ModelStateDictionary();
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(User));
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
var context = new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(User));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal("Could not convert string to decimal: not-an-age. Path 'Age', line 1, position 39.",
|
Assert.Equal(
|
||||||
actionContext.ModelState["Age"].Errors[0].Exception.Message);
|
"Could not convert string to decimal: not-an-age. Path 'Age', line 1, position 39.",
|
||||||
|
modelState["Age"].Errors[0].Exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -139,19 +140,21 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var formatter = new JsonInputFormatter();
|
var formatter = new JsonInputFormatter();
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var modelState = new ModelStateDictionary();
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(User));
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
var context = new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
actionContext.ModelState.MaxAllowedErrors = 3;
|
var context = new InputFormatterContext(httpContext, modelState, typeof(User));
|
||||||
actionContext.ModelState.AddModelError("key1", "error1");
|
|
||||||
actionContext.ModelState.AddModelError("key2", "error2");
|
modelState.MaxAllowedErrors = 3;
|
||||||
|
modelState.AddModelError("key1", "error1");
|
||||||
|
modelState.AddModelError("key2", "error2");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(actionContext.ModelState.ContainsKey("age"));
|
Assert.False(modelState.ContainsKey("age"));
|
||||||
var error = Assert.Single(actionContext.ModelState[""].Errors);
|
var error = Assert.Single(modelState[""].Errors);
|
||||||
Assert.IsType<TooManyModelErrorsException>(error.Exception);
|
Assert.IsType<TooManyModelErrorsException>(error.Exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,17 +192,18 @@ namespace Microsoft.AspNet.Mvc
|
||||||
// by default we ignore missing members, so here explicitly changing it
|
// by default we ignore missing members, so here explicitly changing it
|
||||||
jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
|
jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, "application/json;charset=utf-8");
|
var modelState = new ModelStateDictionary();
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(UserLogin));
|
var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8");
|
||||||
var inputFormatterContext = new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
|
var inputFormatterContext = new InputFormatterContext(httpContext, modelState, typeof(UserLogin));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var obj = await jsonFormatter.ReadAsync(inputFormatterContext);
|
var obj = await jsonFormatter.ReadAsync(inputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(actionContext.ModelState.IsValid);
|
Assert.False(modelState.IsValid);
|
||||||
|
|
||||||
var modelErrorMessage = actionContext.ModelState.Values.First().Errors[0].Exception.Message;
|
var modelErrorMessage = modelState.Values.First().Errors[0].Exception.Message;
|
||||||
Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage);
|
Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -217,51 +221,24 @@ namespace Microsoft.AspNet.Mvc
|
||||||
MissingMemberHandling = MissingMemberHandling.Error
|
MissingMemberHandling = MissingMemberHandling.Error
|
||||||
};
|
};
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, "application/json;charset=utf-8");
|
var modelState = new ModelStateDictionary();
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(UserLogin));
|
var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8");
|
||||||
var inputFormatterContext = new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
|
var inputFormatterContext = new InputFormatterContext(httpContext, modelState, typeof(UserLogin));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var obj = await jsonFormatter.ReadAsync(inputFormatterContext);
|
var obj = await jsonFormatter.ReadAsync(inputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.False(actionContext.ModelState.IsValid);
|
Assert.False(modelState.IsValid);
|
||||||
|
|
||||||
var modelErrorMessage = actionContext.ModelState.Values.First().Errors[0].Exception.Message;
|
var modelErrorMessage = modelState.Values.First().Errors[0].Exception.Message;
|
||||||
Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage);
|
Assert.Contains("Required property 'Password' not found in JSON", modelErrorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
private static HttpContext GetHttpContext(
|
||||||
public async Task Validation_DoesNotHappen_ForNonRequired_ValueTypeProperties()
|
byte[] contentBytes,
|
||||||
{
|
string contentType = "application/json")
|
||||||
// Arrange
|
|
||||||
var contentBytes = Encoding.UTF8.GetBytes("{\"Name\":\"Seattle\"}");
|
|
||||||
var jsonFormatter = new JsonInputFormatter();
|
|
||||||
var actionContext = GetActionContext(contentBytes, "application/json;charset=utf-8");
|
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(Location));
|
|
||||||
var inputFormatterContext = new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
|
|
||||||
// Act
|
|
||||||
var obj = await jsonFormatter.ReadAsync(inputFormatterContext);
|
|
||||||
|
|
||||||
// Assert
|
|
||||||
Assert.True(actionContext.ModelState.IsValid);
|
|
||||||
var location = obj as Location;
|
|
||||||
Assert.NotNull(location);
|
|
||||||
Assert.Equal(0, location.Id);
|
|
||||||
Assert.Equal("Seattle", location.Name);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ActionContext GetActionContext(byte[] contentBytes,
|
|
||||||
string contentType = "application/xml")
|
|
||||||
{
|
|
||||||
return new ActionContext(GetHttpContext(contentBytes, contentType),
|
|
||||||
new AspNet.Routing.RouteData(),
|
|
||||||
new ActionDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpContext GetHttpContext(byte[] contentBytes,
|
|
||||||
string contentType = "application/json")
|
|
||||||
{
|
{
|
||||||
var request = new Mock<HttpRequest>();
|
var request = new Mock<HttpRequest>();
|
||||||
var headers = new Mock<IHeaderDictionary>();
|
var headers = new Mock<IHeaderDictionary>();
|
||||||
|
|
|
||||||
|
|
@ -62,11 +62,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
|
||||||
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext);
|
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
|
||||||
Assert.Equal(expectedOutput,
|
Assert.NotNull(body);
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
body.Position = 0;
|
||||||
.ReadToEnd());
|
|
||||||
|
var content = new StreamReader(body, Encoding.UTF8).ReadToEnd();
|
||||||
|
Assert.Equal(expectedOutput, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -93,11 +95,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
|
||||||
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext);
|
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
|
||||||
|
|
||||||
var streamReader = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8);
|
Assert.NotNull(body);
|
||||||
Assert.Equal(expectedOutput, streamReader.ReadToEnd());
|
body.Position = 0;
|
||||||
|
|
||||||
|
var content = new StreamReader(body, Encoding.UTF8).ReadToEnd();
|
||||||
|
Assert.Equal(expectedOutput, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -155,12 +159,14 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
|
||||||
var encoding = CreateOrGetSupportedEncoding(formatter, encodingAsString, isDefaultEncoding);
|
var encoding = CreateOrGetSupportedEncoding(formatter, encodingAsString, isDefaultEncoding);
|
||||||
var expectedData = encoding.GetBytes(formattedContent);
|
var expectedData = encoding.GetBytes(formattedContent);
|
||||||
|
|
||||||
var memStream = new MemoryStream();
|
|
||||||
|
var body = new MemoryStream();
|
||||||
|
var actionContext = GetActionContext(MediaTypeHeaderValue.Parse(mediaType), body);
|
||||||
var outputFormatterContext = new OutputFormatterContext
|
var outputFormatterContext = new OutputFormatterContext
|
||||||
{
|
{
|
||||||
Object = content,
|
Object = content,
|
||||||
DeclaredType = typeof(string),
|
DeclaredType = typeof(string),
|
||||||
ActionContext = GetActionContext(MediaTypeHeaderValue.Parse(mediaType), memStream),
|
HttpContext = actionContext.HttpContext,
|
||||||
SelectedEncoding = encoding
|
SelectedEncoding = encoding
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -168,7 +174,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
|
||||||
await formatter.WriteResponseBodyAsync(outputFormatterContext);
|
await formatter.WriteResponseBodyAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var actualData = memStream.ToArray();
|
var actualData = body.ToArray();
|
||||||
Assert.Equal(expectedData, actualData);
|
Assert.Equal(expectedData, actualData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -200,11 +206,12 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
|
||||||
{
|
{
|
||||||
var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType);
|
var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType);
|
||||||
|
|
||||||
|
var actionContext = GetActionContext(mediaTypeHeaderValue, responseStream);
|
||||||
return new OutputFormatterContext
|
return new OutputFormatterContext
|
||||||
{
|
{
|
||||||
Object = outputValue,
|
Object = outputValue,
|
||||||
DeclaredType = outputType,
|
DeclaredType = outputType,
|
||||||
ActionContext = GetActionContext(mediaTypeHeaderValue, responseStream),
|
HttpContext = actionContext.HttpContext,
|
||||||
SelectedEncoding = Encoding.GetEncoding(mediaTypeHeaderValue.Charset)
|
SelectedEncoding = Encoding.GetEncoding(mediaTypeHeaderValue.Charset)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,9 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var content = "[{\"op\":\"add\",\"path\":\"Customer/Name\",\"value\":\"John\"}]";
|
var content = "[{\"op\":\"add\",\"path\":\"Customer/Name\",\"value\":\"John\"}]";
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var modelState = new ModelStateDictionary();
|
||||||
var context = new InputFormatterContext(actionContext, typeof(JsonPatchDocument<Customer>));
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(JsonPatchDocument<Customer>));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
@ -45,8 +46,9 @@ namespace Microsoft.AspNet.Mvc
|
||||||
"{\"op\": \"remove\", \"path\" : \"Customer/Name\"}]";
|
"{\"op\": \"remove\", \"path\" : \"Customer/Name\"}]";
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var modelState = new ModelStateDictionary();
|
||||||
var context = new InputFormatterContext(actionContext, typeof(JsonPatchDocument<Customer>));
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(JsonPatchDocument<Customer>));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
@ -72,8 +74,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
|
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
|
var modelState = new ModelStateDictionary();
|
||||||
var formatterContext = new InputFormatterContext(actionContext, typeof(JsonPatchDocument<Customer>));
|
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
|
||||||
|
var formatterContext = new InputFormatterContext(
|
||||||
|
httpContext,
|
||||||
|
modelState,
|
||||||
|
typeof(JsonPatchDocument<Customer>));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = formatter.CanRead(formatterContext);
|
var result = formatter.CanRead(formatterContext);
|
||||||
|
|
@ -92,8 +98,9 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
|
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: "application/json-patch+json");
|
var modelState = new ModelStateDictionary();
|
||||||
var formatterContext = new InputFormatterContext(actionContext, modelType);
|
var httpContext = GetHttpContext(contentBytes, contentType: "application/json-patch+json");
|
||||||
|
var formatterContext = new InputFormatterContext(httpContext, modelState, modelType);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = formatter.CanRead(formatterContext);
|
var result = formatter.CanRead(formatterContext);
|
||||||
|
|
@ -113,25 +120,20 @@ namespace Microsoft.AspNet.Mvc
|
||||||
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
|
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
|
||||||
var contentBytes = Encoding.UTF8.GetBytes(content);
|
var contentBytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: "application/json-patch+json");
|
var modelState = new ModelStateDictionary();
|
||||||
var context = new InputFormatterContext(actionContext, typeof(Customer));
|
var httpContext = GetHttpContext(contentBytes, contentType: "application/json-patch+json");
|
||||||
|
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(Customer));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Contains(exceptionMessage, actionContext.ModelState[""].Errors[0].Exception.Message);
|
Assert.Contains(exceptionMessage, modelState[""].Errors[0].Exception.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActionContext GetActionContext(byte[] contentBytes,
|
private static HttpContext GetHttpContext(
|
||||||
string contentType = "application/json-patch+json")
|
byte[] contentBytes,
|
||||||
{
|
|
||||||
return new ActionContext(GetHttpContext(contentBytes, contentType),
|
|
||||||
new AspNet.Routing.RouteData(),
|
|
||||||
new ActionDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpContext GetHttpContext(byte[] contentBytes,
|
|
||||||
string contentType = "application/json-patch+json")
|
string contentType = "application/json-patch+json")
|
||||||
{
|
{
|
||||||
var request = new Mock<HttpRequest>();
|
var request = new Mock<HttpRequest>();
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
{
|
{
|
||||||
Object = value,
|
Object = value,
|
||||||
DeclaredType = typeToUse,
|
DeclaredType = typeToUse,
|
||||||
ActionContext = null,
|
HttpContext = null,
|
||||||
};
|
};
|
||||||
var contetType = useNonNullContentType ? MediaTypeHeaderValue.Parse("text/plain") : null;
|
var contetType = useNonNullContentType ? MediaTypeHeaderValue.Parse("text/plain") : null;
|
||||||
var formatter = new HttpNoContentOutputFormatter();
|
var formatter = new HttpNoContentOutputFormatter();
|
||||||
|
|
@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
{
|
{
|
||||||
Object = "Something non null.",
|
Object = "Something non null.",
|
||||||
DeclaredType = declaredType,
|
DeclaredType = declaredType,
|
||||||
ActionContext = null,
|
HttpContext = null,
|
||||||
};
|
};
|
||||||
var contetType = MediaTypeHeaderValue.Parse("text/plain");
|
var contetType = MediaTypeHeaderValue.Parse("text/plain");
|
||||||
var formatter = new HttpNoContentOutputFormatter();
|
var formatter = new HttpNoContentOutputFormatter();
|
||||||
|
|
@ -93,7 +93,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
{
|
{
|
||||||
Object = value,
|
Object = value,
|
||||||
DeclaredType = typeof(string),
|
DeclaredType = typeof(string),
|
||||||
ActionContext = null,
|
HttpContext = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
var contetType = MediaTypeHeaderValue.Parse("text/plain");
|
var contetType = MediaTypeHeaderValue.Parse("text/plain");
|
||||||
|
|
@ -117,7 +117,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
var formatterContext = new OutputFormatterContext()
|
var formatterContext = new OutputFormatterContext()
|
||||||
{
|
{
|
||||||
Object = null,
|
Object = null,
|
||||||
ActionContext = new ActionContext(defaultHttpContext, new RouteData(), new ActionDescriptor())
|
HttpContext = defaultHttpContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
var formatter = new HttpNoContentOutputFormatter();
|
var formatter = new HttpNoContentOutputFormatter();
|
||||||
|
|
@ -137,7 +137,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
var formatterContext = new OutputFormatterContext()
|
var formatterContext = new OutputFormatterContext()
|
||||||
{
|
{
|
||||||
Object = null,
|
Object = null,
|
||||||
ActionContext = new ActionContext(defaultHttpContext, new RouteData(), new ActionDescriptor()),
|
HttpContext = defaultHttpContext,
|
||||||
StatusCode = StatusCodes.Status201Created
|
StatusCode = StatusCodes.Status201Created
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
httpRequest.Headers["Accept-Charset"] = acceptCharsetHeaders;
|
httpRequest.Headers["Accept-Charset"] = acceptCharsetHeaders;
|
||||||
httpRequest.ContentType = "application/acceptCharset;charset=" + requestEncoding;
|
httpRequest.ContentType = "application/acceptCharset;charset=" + requestEncoding;
|
||||||
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
||||||
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
|
|
||||||
var formatter = new TestOutputFormatter();
|
var formatter = new TestOutputFormatter();
|
||||||
foreach (string supportedEncoding in supportedEncodings)
|
foreach (string supportedEncoding in supportedEncodings)
|
||||||
{
|
{
|
||||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
var formatterContext = new OutputFormatterContext()
|
var formatterContext = new OutputFormatterContext()
|
||||||
{
|
{
|
||||||
Object = "someValue",
|
Object = "someValue",
|
||||||
ActionContext = actionContext,
|
HttpContext = mockHttpContext.Object,
|
||||||
DeclaredType = typeof(string)
|
DeclaredType = typeof(string)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -85,8 +85,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
var mockHttpContext = new Mock<HttpContext>();
|
var mockHttpContext = new Mock<HttpContext>();
|
||||||
var httpRequest = new DefaultHttpContext().Request;
|
var httpRequest = new DefaultHttpContext().Request;
|
||||||
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
||||||
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
|
formatterContext.HttpContext = mockHttpContext.Object;
|
||||||
formatterContext.ActionContext = actionContext;
|
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
var ex = Assert.Throws<InvalidOperationException>(
|
var ex = Assert.Throws<InvalidOperationException>(
|
||||||
|
|
@ -108,8 +107,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
var httpRequest = new DefaultHttpContext().Request;
|
var httpRequest = new DefaultHttpContext().Request;
|
||||||
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
|
||||||
mockHttpContext.SetupProperty(o => o.Response.ContentType);
|
mockHttpContext.SetupProperty(o => o.Response.ContentType);
|
||||||
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
|
formatterContext.HttpContext = mockHttpContext.Object;
|
||||||
formatterContext.ActionContext = actionContext;
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
testFormatter.WriteResponseHeaders(formatterContext);
|
testFormatter.WriteResponseHeaders(formatterContext);
|
||||||
|
|
@ -130,10 +128,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
var mediaType = new MediaTypeHeaderValue("image/png");
|
var mediaType = new MediaTypeHeaderValue("image/png");
|
||||||
formatter.SupportedMediaTypes.Add(mediaType);
|
formatter.SupportedMediaTypes.Add(mediaType);
|
||||||
var formatterContext = new OutputFormatterContext();
|
var formatterContext = new OutputFormatterContext();
|
||||||
formatterContext.ActionContext = new ActionContext(
|
formatterContext.HttpContext = new DefaultHttpContext();
|
||||||
new DefaultHttpContext(),
|
|
||||||
new RouteData(),
|
|
||||||
new ActionDescriptor());
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
await formatter.WriteAsync(formatterContext);
|
await formatter.WriteAsync(formatterContext);
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc
|
||||||
{
|
{
|
||||||
Object = null,
|
Object = null,
|
||||||
DeclaredType = typeof(string),
|
DeclaredType = typeof(string),
|
||||||
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()),
|
HttpContext = mockHttpContext.Object,
|
||||||
SelectedEncoding = encoding
|
SelectedEncoding = encoding
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShimTest
|
||||||
{
|
{
|
||||||
Object = outputValue,
|
Object = outputValue,
|
||||||
DeclaredType = outputType,
|
DeclaredType = outputType,
|
||||||
ActionContext = new ActionContext(httpContext, routeData: null, actionDescriptor: null)
|
HttpContext = httpContext,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,9 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
var formatter = new XmlDataContractSerializerInputFormatter();
|
var formatter = new XmlDataContractSerializerInputFormatter();
|
||||||
var contentBytes = Encoding.UTF8.GetBytes("content");
|
var contentBytes = Encoding.UTF8.GetBytes("content");
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
|
var modelState = new ModelStateDictionary();
|
||||||
var formatterContext = new InputFormatterContext(actionContext, typeof(string));
|
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
|
||||||
|
var formatterContext = new InputFormatterContext(httpContext, modelState, typeof(string));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = formatter.CanRead(formatterContext);
|
var result = formatter.CanRead(formatterContext);
|
||||||
|
|
@ -285,7 +286,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(model);
|
Assert.NotNull(model);
|
||||||
Assert.True(context.ActionContext.HttpContext.Request.Body.CanRead);
|
Assert.True(context.HttpContext.Request.Body.CanRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -328,8 +329,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
"<DummyClass><SampleInt>1000</SampleInt></DummyClass>");
|
"<DummyClass><SampleInt>1000</SampleInt></DummyClass>");
|
||||||
|
|
||||||
var formatter = new XmlDataContractSerializerInputFormatter();
|
var formatter = new XmlDataContractSerializerInputFormatter();
|
||||||
var actionContext = GetActionContext(inputBytes, contentType: "application/xml; charset=utf-16");
|
|
||||||
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
|
var modelState = new ModelStateDictionary();
|
||||||
|
var httpContext = GetHttpContext(inputBytes, contentType: "application/xml; charset=utf-16");
|
||||||
|
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(TestLevelOne));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
|
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
|
||||||
|
|
@ -381,8 +385,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
var formatter = new XmlDataContractSerializerInputFormatter();
|
var formatter = new XmlDataContractSerializerInputFormatter();
|
||||||
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
|
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: "application/xml; charset=utf-16");
|
var modelState = new ModelStateDictionary();
|
||||||
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
|
var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");
|
||||||
|
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(TestLevelOne));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
@ -530,10 +536,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(98052, model[0].Zipcode);
|
Assert.Equal(98052, model[0].Zipcode);
|
||||||
Assert.Equal(true, model[0].IsResidential);
|
Assert.Equal(true, model[0].IsResidential);
|
||||||
|
|
||||||
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(1, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
||||||
|
|
@ -564,10 +570,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(98052, model.Zipcode);
|
Assert.Equal(98052, model.Zipcode);
|
||||||
Assert.Equal(true, model.IsResidential);
|
Assert.Equal(true, model.IsResidential);
|
||||||
|
|
||||||
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(1, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
||||||
|
|
@ -603,10 +609,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(98052, model.AddressProperty.Zipcode);
|
Assert.Equal(98052, model.AddressProperty.Zipcode);
|
||||||
Assert.Equal(true, model.AddressProperty.IsResidential);
|
Assert.Equal(true, model.AddressProperty.IsResidential);
|
||||||
|
|
||||||
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(1, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
||||||
|
|
@ -640,11 +646,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(98052, model.Addresses[0].Zipcode);
|
Assert.Equal(98052, model.Addresses[0].Zipcode);
|
||||||
Assert.Equal(true, model.Addresses[0].IsResidential);
|
Assert.Equal(true, model.Addresses[0].IsResidential);
|
||||||
|
|
||||||
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(1, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
modelStateKey: typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
actionContext: context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName)
|
||||||
|
|
@ -676,10 +682,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(98052, model.Zipcode);
|
Assert.Equal(98052, model.Zipcode);
|
||||||
Assert.Equal(true, model.IsResidential);
|
Assert.Equal(true, model.IsResidential);
|
||||||
|
|
||||||
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(1, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
||||||
|
|
@ -710,7 +716,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.NotNull(model);
|
Assert.NotNull(model);
|
||||||
Assert.Equal(expectedModel.Year, model.Year);
|
Assert.Equal(expectedModel.Year, model.Year);
|
||||||
Assert.Equal(expectedModel.ServicedYears, model.ServicedYears);
|
Assert.Equal(expectedModel.ServicedYears, model.ServicedYears);
|
||||||
Assert.Empty(context.ActionContext.ModelState);
|
Assert.Empty(context.ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -745,7 +751,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.NotNull(model.CarInfoProperty);
|
Assert.NotNull(model.CarInfoProperty);
|
||||||
Assert.Equal(expectedModel.CarInfoProperty.Year, model.CarInfoProperty.Year);
|
Assert.Equal(expectedModel.CarInfoProperty.Year, model.CarInfoProperty.Year);
|
||||||
Assert.Equal(expectedModel.CarInfoProperty.ServicedYears, model.CarInfoProperty.ServicedYears);
|
Assert.Equal(expectedModel.CarInfoProperty.ServicedYears, model.CarInfoProperty.ServicedYears);
|
||||||
Assert.Empty(context.ActionContext.ModelState);
|
Assert.Empty(context.ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -781,10 +787,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(expectedModel.Manager.Name, model.Manager.Name);
|
Assert.Equal(expectedModel.Manager.Name, model.Manager.Name);
|
||||||
Assert.Null(model.Manager.Manager);
|
Assert.Null(model.Manager.Manager);
|
||||||
|
|
||||||
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(1, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Employee).FullName,
|
typeof(Employee).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
|
||||||
|
|
@ -810,7 +816,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.NotNull(model);
|
Assert.NotNull(model);
|
||||||
Assert.Equal(10, model.Id);
|
Assert.Equal(10, model.Id);
|
||||||
Assert.Equal(true, model.SupportsVirtualization);
|
Assert.Equal(true, model.SupportsVirtualization);
|
||||||
Assert.Empty(context.ActionContext.ModelState);
|
Assert.Empty(context.ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -833,7 +839,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(1, model.Count);
|
Assert.Equal(1, model.Count);
|
||||||
Assert.Equal(10, model[0].Id);
|
Assert.Equal(10, model[0].Id);
|
||||||
Assert.Equal(true, model[0].SupportsVirtualization);
|
Assert.Equal(true, model[0].SupportsVirtualization);
|
||||||
Assert.Empty(context.ActionContext.ModelState);
|
Assert.Empty(context.ModelState);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -855,10 +861,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.NotNull(model);
|
Assert.NotNull(model);
|
||||||
Assert.Equal(10, model.Id);
|
Assert.Equal(10, model.Id);
|
||||||
|
|
||||||
Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(2, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Product).FullName,
|
typeof(Product).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
|
||||||
|
|
@ -866,7 +872,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
||||||
|
|
@ -895,10 +901,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
Assert.Equal(10, model[0].Id);
|
Assert.Equal(10, model[0].Id);
|
||||||
Assert.Equal("Phone", model[0].Name);
|
Assert.Equal("Phone", model[0].Name);
|
||||||
|
|
||||||
Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(2, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Product).FullName,
|
typeof(Product).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
|
||||||
|
|
@ -906,7 +912,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
|
||||||
|
|
@ -931,10 +937,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Null(model);
|
Assert.Null(model);
|
||||||
|
|
||||||
Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(3, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
|
||||||
|
|
@ -943,7 +949,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Employee).FullName,
|
typeof(Employee).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
|
||||||
|
|
@ -951,7 +957,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Product).FullName,
|
typeof(Product).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
|
||||||
|
|
@ -976,17 +982,17 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Null(model);
|
Assert.Null(model);
|
||||||
|
|
||||||
Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(3, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(School).FullName,
|
typeof(School).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(School.Id), typeof(School).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(School.Id), typeof(School).FullName)
|
||||||
});
|
});
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Website).FullName,
|
typeof(Website).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Website.Id), typeof(Website).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Website.Id), typeof(Website).FullName)
|
||||||
|
|
@ -994,7 +1000,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Student).FullName,
|
typeof(Student).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Student.Id), typeof(Student).FullName)
|
string.Format(requiredErrorMessageFormat, nameof(Student.Id), typeof(Student).FullName)
|
||||||
|
|
@ -1019,10 +1025,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Null(model);
|
Assert.Null(model);
|
||||||
|
|
||||||
Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(2, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Point).FullName,
|
typeof(Point).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
|
||||||
|
|
@ -1030,7 +1036,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
});
|
});
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Address).FullName,
|
typeof(Address).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
|
||||||
|
|
@ -1056,10 +1062,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Null(model);
|
Assert.Null(model);
|
||||||
|
|
||||||
Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
|
Assert.Equal(3, context.ModelState.Keys.Count);
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(Point).FullName,
|
typeof(Point).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
|
string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
|
||||||
|
|
@ -1067,7 +1073,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
});
|
});
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(GpsCoordinate).FullName,
|
typeof(GpsCoordinate).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(
|
string.Format(
|
||||||
|
|
@ -1081,7 +1087,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
});
|
});
|
||||||
AssertModelStateErrorMessages(
|
AssertModelStateErrorMessages(
|
||||||
typeof(ValueTypePropertiesModel).FullName,
|
typeof(ValueTypePropertiesModel).FullName,
|
||||||
context.ActionContext,
|
context,
|
||||||
expectedErrorMessages: new[]
|
expectedErrorMessages: new[]
|
||||||
{
|
{
|
||||||
string.Format(
|
string.Format(
|
||||||
|
|
@ -1105,11 +1111,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
private void AssertModelStateErrorMessages(
|
private void AssertModelStateErrorMessages(
|
||||||
string modelStateKey,
|
string modelStateKey,
|
||||||
ActionContext actionContext,
|
InputFormatterContext context,
|
||||||
IEnumerable<string> expectedErrorMessages)
|
IEnumerable<string> expectedErrorMessages)
|
||||||
{
|
{
|
||||||
ModelState modelState;
|
ModelState modelState;
|
||||||
actionContext.ModelState.TryGetValue(modelStateKey, out modelState);
|
context.ModelState.TryGetValue(modelStateKey, out modelState);
|
||||||
|
|
||||||
Assert.NotNull(modelState);
|
Assert.NotNull(modelState);
|
||||||
Assert.NotEmpty(modelState.Errors);
|
Assert.NotEmpty(modelState.Errors);
|
||||||
|
|
@ -1140,20 +1146,13 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
|
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
|
||||||
{
|
{
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType);
|
return new InputFormatterContext(httpContext, new ModelStateDictionary(), modelType);
|
||||||
return new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActionContext GetActionContext(byte[] contentBytes,
|
private static HttpContext GetHttpContext(
|
||||||
string contentType = "application/xml")
|
byte[] contentBytes,
|
||||||
{
|
string contentType = "application/xml")
|
||||||
return new ActionContext(GetHttpContext(contentBytes, contentType),
|
|
||||||
new AspNet.Routing.RouteData(),
|
|
||||||
new ActionDescriptor());
|
|
||||||
}
|
|
||||||
private static HttpContext GetHttpContext(byte[] contentBytes,
|
|
||||||
string contentType = "application/xml")
|
|
||||||
{
|
{
|
||||||
var request = new Mock<HttpRequest>();
|
var request = new Mock<HttpRequest>();
|
||||||
var headers = new Mock<IHeaderDictionary>();
|
var headers = new Mock<IHeaderDictionary>();
|
||||||
|
|
|
||||||
|
|
@ -102,12 +102,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal(expectedOutput,
|
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
.ReadToEnd());
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -158,17 +157,22 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(writerSettings, formatter.WriterSettings);
|
Assert.Same(writerSettings, formatter.WriterSettings);
|
||||||
var responseStream = formatterContext.ActionContext.HttpContext.Response.Body;
|
|
||||||
Assert.NotNull(responseStream);
|
var body = formatterContext.HttpContext.Response.Body;
|
||||||
responseStream.Position = 0;
|
body.Position = 0;
|
||||||
var actualOutput = new StreamReader(responseStream, Encoding.UTF8).ReadToEnd();
|
|
||||||
XmlAssert.Equal(expectedOutput, actualOutput);
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WriteAsync_WritesSimpleTypes()
|
public async Task WriteAsync_WritesSimpleTypes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleInt>10</SampleInt></DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var formatter = new XmlDataContractSerializerOutputFormatter();
|
var formatter = new XmlDataContractSerializerOutputFormatter();
|
||||||
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
@ -177,18 +181,23 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
|
||||||
"<SampleInt>10</SampleInt></DummyClass>",
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
.ReadToEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WriteAsync_WritesComplexTypes()
|
public async Task WriteAsync_WritesComplexTypes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<TestLevelTwo xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleString>TestString</SampleString>" +
|
||||||
|
"<TestOne><SampleInt>10</SampleInt><sampleString>TestLevelOne string</sampleString>" +
|
||||||
|
"</TestOne></TestLevelTwo>";
|
||||||
|
|
||||||
var sampleInput = new TestLevelTwo
|
var sampleInput = new TestLevelTwo
|
||||||
{
|
{
|
||||||
SampleString = "TestString",
|
SampleString = "TestString",
|
||||||
|
|
@ -205,24 +214,26 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<TestLevelTwo xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
|
||||||
"<SampleString>TestString</SampleString>" +
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
"<TestOne><SampleInt>10</SampleInt><sampleString>TestLevelOne string</sampleString>" +
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
"</TestOne></TestLevelTwo>",
|
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
|
||||||
.ReadToEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WriteAsync_WritesOnModifiedWriterSettings()
|
public async Task WriteAsync_WritesOnModifiedWriterSettings()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
|
||||||
|
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleInt>10</SampleInt></DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
var formatter = new XmlDataContractSerializerOutputFormatter(
|
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||||
new System.Xml.XmlWriterSettings
|
new XmlWriterSettings
|
||||||
{
|
{
|
||||||
OmitXmlDeclaration = false,
|
OmitXmlDeclaration = false,
|
||||||
CloseOutput = false
|
CloseOutput = false
|
||||||
|
|
@ -232,19 +243,22 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
|
|
||||||
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
"<SampleInt>10</SampleInt></DummyClass>",
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
|
||||||
Encoding.UTF8).ReadToEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WriteAsync_WritesUTF16Output()
|
public async Task WriteAsync_WritesUTF16Output()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
|
||||||
|
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleInt>10</SampleInt></DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType(),
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType(),
|
||||||
"application/xml; charset=utf-16");
|
"application/xml; charset=utf-16");
|
||||||
|
|
@ -255,19 +269,21 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
|
|
||||||
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
"<SampleInt>10</SampleInt></DummyClass>",
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
|
||||||
Encodings.UTF16EncodingLittleEndian).ReadToEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WriteAsync_WritesIndentedOutput()
|
public async Task WriteAsync_WritesIndentedOutput()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"\r\n <SampleInt>10</SampleInt>\r\n</DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var formatter = new XmlDataContractSerializerOutputFormatter();
|
var formatter = new XmlDataContractSerializerOutputFormatter();
|
||||||
formatter.WriterSettings.Indent = true;
|
formatter.WriterSettings.Indent = true;
|
||||||
|
|
@ -277,13 +293,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
var outputString = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
|
||||||
Encoding.UTF8).ReadToEnd();
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
XmlAssert.Equal("<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
"\r\n <SampleInt>10</SampleInt>\r\n</DummyClass>",
|
|
||||||
outputString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -298,8 +312,8 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
Assert.True(body.CanRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -310,7 +324,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
var formatter = new XmlDataContractSerializerOutputFormatter();
|
var formatter = new XmlDataContractSerializerOutputFormatter();
|
||||||
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
var response = outputFormatterContext.ActionContext.HttpContext.Response;
|
var response = outputFormatterContext.HttpContext.Response;
|
||||||
response.Body = FlushReportingStream.GetThrowingStream();
|
response.Body = FlushReportingStream.GetThrowingStream();
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
|
|
@ -447,11 +461,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
var actualOutput = new StreamReader(
|
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8).ReadToEnd();
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
XmlAssert.Equal(expectedOutput, actualOutput);
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -491,11 +505,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
var actualOutput = new StreamReader(
|
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8).ReadToEnd();
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
XmlAssert.Equal(expectedOutput, actualOutput);
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -535,11 +549,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
var actualOutput = new StreamReader(
|
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8).ReadToEnd();
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
XmlAssert.Equal(expectedOutput, actualOutput);
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
|
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
|
||||||
|
|
@ -549,23 +563,26 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
{
|
{
|
||||||
Object = outputValue,
|
Object = outputValue,
|
||||||
DeclaredType = outputType,
|
DeclaredType = outputType,
|
||||||
ActionContext = GetActionContext(contentType)
|
HttpContext = GetHttpContext(contentType)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActionContext GetActionContext(string contentType)
|
private static HttpContext GetHttpContext(string contentType)
|
||||||
{
|
{
|
||||||
var request = new Mock<HttpRequest>();
|
var request = new Mock<HttpRequest>();
|
||||||
|
|
||||||
var headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
|
var headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
|
||||||
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
|
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
|
||||||
request.Setup(r => r.ContentType).Returns(contentType);
|
request.Setup(r => r.ContentType).Returns(contentType);
|
||||||
request.SetupGet(r => r.Headers).Returns(headers);
|
request.SetupGet(r => r.Headers).Returns(headers);
|
||||||
|
|
||||||
var response = new Mock<HttpResponse>();
|
var response = new Mock<HttpResponse>();
|
||||||
response.SetupGet(f => f.Body).Returns(new MemoryStream());
|
response.SetupGet(f => f.Body).Returns(new MemoryStream());
|
||||||
|
|
||||||
var httpContext = new Mock<HttpContext>();
|
var httpContext = new Mock<HttpContext>();
|
||||||
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
||||||
httpContext.SetupGet(c => c.Response).Returns(response.Object);
|
httpContext.SetupGet(c => c.Response).Returns(response.Object);
|
||||||
return new ActionContext(httpContext.Object, routeData: null, actionDescriptor: null);
|
return httpContext.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestXmlDataContractSerializerOutputFormatter : XmlDataContractSerializerOutputFormatter
|
private class TestXmlDataContractSerializerOutputFormatter : XmlDataContractSerializerOutputFormatter
|
||||||
|
|
|
||||||
|
|
@ -56,8 +56,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
var formatter = new XmlSerializerInputFormatter();
|
var formatter = new XmlSerializerInputFormatter();
|
||||||
var contentBytes = Encoding.UTF8.GetBytes("content");
|
var contentBytes = Encoding.UTF8.GetBytes("content");
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
|
var modelState = new ModelStateDictionary();
|
||||||
var formatterContext = new InputFormatterContext(actionContext, typeof(string));
|
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
|
||||||
|
|
||||||
|
var formatterContext = new InputFormatterContext(httpContext, modelState, typeof(string));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = formatter.CanRead(formatterContext);
|
var result = formatter.CanRead(formatterContext);
|
||||||
|
|
@ -292,7 +294,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(model);
|
Assert.NotNull(model);
|
||||||
Assert.True(context.ActionContext.HttpContext.Request.Body.CanRead);
|
Assert.True(context.HttpContext.Request.Body.CanRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -337,8 +339,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
"<DummyClass><SampleInt>1000</SampleInt></DummyClass>");
|
"<DummyClass><SampleInt>1000</SampleInt></DummyClass>");
|
||||||
|
|
||||||
var formatter = new XmlSerializerInputFormatter();
|
var formatter = new XmlSerializerInputFormatter();
|
||||||
var actionContext = GetActionContext(inputBytes, contentType: "application/xml; charset=utf-16");
|
|
||||||
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
|
var modelState = new ModelStateDictionary();
|
||||||
|
var httpContext = GetHttpContext(inputBytes, contentType: "application/xml; charset=utf-16");
|
||||||
|
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(TestLevelOne));
|
||||||
|
|
||||||
// Act and Assert
|
// Act and Assert
|
||||||
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
|
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
|
||||||
|
|
@ -392,8 +397,9 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
var formatter = new XmlSerializerInputFormatter();
|
var formatter = new XmlSerializerInputFormatter();
|
||||||
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
|
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
|
||||||
|
|
||||||
var actionContext = GetActionContext(contentBytes, contentType: "application/xml; charset=utf-16");
|
var modelState = new ModelStateDictionary();
|
||||||
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
|
var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");
|
||||||
|
var context = new InputFormatterContext(httpContext, modelState, typeof(TestLevelOne));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = await formatter.ReadAsync(context);
|
var model = await formatter.ReadAsync(context);
|
||||||
|
|
@ -410,21 +416,13 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
|
|
||||||
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
|
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
|
||||||
{
|
{
|
||||||
var actionContext = GetActionContext(contentBytes);
|
var httpContext = GetHttpContext(contentBytes);
|
||||||
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType);
|
return new InputFormatterContext(httpContext, new ModelStateDictionary(), modelType);
|
||||||
return new InputFormatterContext(actionContext, metadata.ModelType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActionContext GetActionContext(byte[] contentBytes,
|
private static HttpContext GetHttpContext(
|
||||||
string contentType = "application/xml")
|
byte[] contentBytes,
|
||||||
{
|
string contentType = "application/xml")
|
||||||
return new ActionContext(GetHttpContext(contentBytes, contentType),
|
|
||||||
new AspNet.Routing.RouteData(),
|
|
||||||
new ActionDescriptor());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpContext GetHttpContext(byte[] contentBytes,
|
|
||||||
string contentType = "application/xml")
|
|
||||||
{
|
{
|
||||||
var request = new Mock<HttpRequest>();
|
var request = new Mock<HttpRequest>();
|
||||||
var headers = new Mock<IHeaderDictionary>();
|
var headers = new Mock<IHeaderDictionary>();
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal(expectedOutput,
|
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
.ReadToEnd());
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -115,18 +114,21 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(formatterContext);
|
await formatter.WriteAsync(formatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Same(writerSettings, formatter.WriterSettings);
|
var body = formatterContext.HttpContext.Response.Body;
|
||||||
var responseStream = formatterContext.ActionContext.HttpContext.Response.Body;
|
body.Position = 0;
|
||||||
Assert.NotNull(responseStream);
|
|
||||||
responseStream.Position = 0;
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
var actualOutput = new StreamReader(responseStream, Encoding.UTF8).ReadToEnd();
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
XmlAssert.Equal(expectedOutput, actualOutput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task XmlSerializerOutputFormatterWritesSimpleTypes()
|
public async Task XmlSerializerOutputFormatterWritesSimpleTypes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var formatter = new XmlSerializerOutputFormatter();
|
var formatter = new XmlSerializerOutputFormatter();
|
||||||
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
@ -135,19 +137,23 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
|
||||||
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
.ReadToEnd());
|
|
||||||
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task XmlSerializerOutputFormatterWritesComplexTypes()
|
public async Task XmlSerializerOutputFormatterWritesComplexTypes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<TestLevelTwo xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleString>TestString</SampleString>" +
|
||||||
|
"<TestOne><sampleString>TestLevelOne string</sampleString>" +
|
||||||
|
"<SampleInt>10</SampleInt></TestOne></TestLevelTwo>";
|
||||||
|
|
||||||
var sampleInput = new TestLevelTwo
|
var sampleInput = new TestLevelTwo
|
||||||
{
|
{
|
||||||
SampleString = "TestString",
|
SampleString = "TestString",
|
||||||
|
|
@ -164,20 +170,22 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<TestLevelTwo xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
|
||||||
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleString>TestString</SampleString>" +
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
"<TestOne><sampleString>TestLevelOne string</sampleString>" +
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
"<SampleInt>10</SampleInt></TestOne></TestLevelTwo>",
|
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
|
||||||
.ReadToEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task XmlSerializerOutputFormatterWritesOnModifiedWriterSettings()
|
public async Task XmlSerializerOutputFormatterWritesOnModifiedWriterSettings()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
|
||||||
|
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
var formatter = new XmlSerializerOutputFormatter(
|
var formatter = new XmlSerializerOutputFormatter(
|
||||||
|
|
@ -191,19 +199,22 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
|
|
||||||
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
|
||||||
.ReadToEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task XmlSerializerOutputFormatterWritesUTF16Output()
|
public async Task XmlSerializerOutputFormatterWritesUTF16Output()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
|
||||||
|
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var outputFormatterContext =
|
var outputFormatterContext =
|
||||||
GetOutputFormatterContext(sampleInput, sampleInput.GetType(), "application/xml; charset=utf-16");
|
GetOutputFormatterContext(sampleInput, sampleInput.GetType(), "application/xml; charset=utf-16");
|
||||||
|
|
@ -214,19 +225,21 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
XmlAssert.Equal("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
|
|
||||||
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
|
||||||
Encodings.UTF16EncodingLittleEndian).ReadToEnd());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task XmlSerializerOutputFormatterWritesIndentedOutput()
|
public async Task XmlSerializerOutputFormatterWritesIndentedOutput()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
var expectedOutput =
|
||||||
|
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <SampleInt>10</SampleInt>\r\n</DummyClass>";
|
||||||
|
|
||||||
var sampleInput = new DummyClass { SampleInt = 10 };
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
var formatter = new XmlSerializerOutputFormatter();
|
var formatter = new XmlSerializerOutputFormatter();
|
||||||
formatter.WriterSettings.Indent = true;
|
formatter.WriterSettings.Indent = true;
|
||||||
|
|
@ -236,13 +249,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
var body = outputFormatterContext.HttpContext.Response.Body;
|
||||||
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
body.Position = 0;
|
||||||
var outputString = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
|
||||||
Encoding.UTF8).ReadToEnd();
|
var content = new StreamReader(body).ReadToEnd();
|
||||||
XmlAssert.Equal("<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
XmlAssert.Equal(expectedOutput, content);
|
||||||
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <SampleInt>10</SampleInt>\r\n</DummyClass>",
|
|
||||||
outputString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -257,8 +268,8 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
await formatter.WriteAsync(outputFormatterContext);
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
Assert.NotNull(outputFormatterContext.HttpContext.Response.Body);
|
||||||
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
Assert.True(outputFormatterContext.HttpContext.Response.Body.CanRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<object[]> TypesForCanWriteResult
|
public static IEnumerable<object[]> TypesForCanWriteResult
|
||||||
|
|
@ -304,7 +315,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
var formatter = new XmlSerializerOutputFormatter();
|
var formatter = new XmlSerializerOutputFormatter();
|
||||||
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
var response = outputFormatterContext.ActionContext.HttpContext.Response;
|
var response = outputFormatterContext.HttpContext.Response;
|
||||||
response.Body = FlushReportingStream.GetThrowingStream();
|
response.Body = FlushReportingStream.GetThrowingStream();
|
||||||
|
|
||||||
// Act & Assert
|
// Act & Assert
|
||||||
|
|
@ -346,30 +357,35 @@ namespace Microsoft.AspNet.Mvc.Xml
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
|
private OutputFormatterContext GetOutputFormatterContext(
|
||||||
string contentType = "application/xml; charset=utf-8")
|
object outputValue,
|
||||||
|
Type outputType,
|
||||||
|
string contentType = "application/xml; charset=utf-8")
|
||||||
{
|
{
|
||||||
return new OutputFormatterContext
|
return new OutputFormatterContext
|
||||||
{
|
{
|
||||||
Object = outputValue,
|
Object = outputValue,
|
||||||
DeclaredType = outputType,
|
DeclaredType = outputType,
|
||||||
ActionContext = GetActionContext(contentType)
|
HttpContext = GetHttpContext(contentType)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ActionContext GetActionContext(string contentType)
|
private static HttpContext GetHttpContext(string contentType)
|
||||||
{
|
{
|
||||||
var request = new Mock<HttpRequest>();
|
var request = new Mock<HttpRequest>();
|
||||||
|
|
||||||
var headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
|
var headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
|
||||||
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
|
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
|
||||||
request.Setup(r => r.ContentType).Returns(contentType);
|
request.Setup(r => r.ContentType).Returns(contentType);
|
||||||
request.SetupGet(r => r.Headers).Returns(headers);
|
request.SetupGet(r => r.Headers).Returns(headers);
|
||||||
|
|
||||||
var response = new Mock<HttpResponse>();
|
var response = new Mock<HttpResponse>();
|
||||||
response.SetupGet(f => f.Body).Returns(new MemoryStream());
|
response.SetupGet(f => f.Body).Returns(new MemoryStream());
|
||||||
|
|
||||||
var httpContext = new Mock<HttpContext>();
|
var httpContext = new Mock<HttpContext>();
|
||||||
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
||||||
httpContext.SetupGet(c => c.Response).Returns(response.Object);
|
httpContext.SetupGet(c => c.Response).Returns(response.Object);
|
||||||
return new ActionContext(httpContext.Object, routeData: null, actionDescriptor: null);
|
return httpContext.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestXmlSerializerOutputFormatter : XmlSerializerOutputFormatter
|
private class TestXmlSerializerOutputFormatter : XmlSerializerOutputFormatter
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace ContentNegotiationWebSite
|
||||||
|
|
||||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
response.ContentType = ContentType + ";charset=utf-8";
|
response.ContentType = ContentType + ";charset=utf-8";
|
||||||
await response.WriteAsync(context.Object.ToString());
|
await response.WriteAsync(context.Object.ToString());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ namespace ContentNegotiationWebSite
|
||||||
|
|
||||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
response.ContentType = "text/plain;charset=utf-8";
|
response.ContentType = "text/plain;charset=utf-8";
|
||||||
await response.WriteAsync(context.Object as string);
|
await response.WriteAsync(context.Object as string);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace ContentNegotiationWebSite
|
||||||
builder.AppendLine();
|
builder.AppendLine();
|
||||||
builder.AppendLine("END:VCARD");
|
builder.AppendLine("END:VCARD");
|
||||||
|
|
||||||
var responseStream = new NonDisposableStream(context.ActionContext.HttpContext.Response.Body);
|
var responseStream = new NonDisposableStream(context.HttpContext.Response.Body);
|
||||||
using (var writer = new StreamWriter(responseStream, context.SelectedEncoding, bufferSize: 1024))
|
using (var writer = new StreamWriter(responseStream, context.SelectedEncoding, bufferSize: 1024))
|
||||||
{
|
{
|
||||||
await writer.WriteAsync(builder.ToString());
|
await writer.WriteAsync(builder.ToString());
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ namespace ContentNegotiationWebSite
|
||||||
builder.AppendLine();
|
builder.AppendLine();
|
||||||
builder.AppendLine("END:VCARD");
|
builder.AppendLine("END:VCARD");
|
||||||
|
|
||||||
var responseStream = new NonDisposableStream(context.ActionContext.HttpContext.Response.Body);
|
var responseStream = new NonDisposableStream(context.HttpContext.Response.Body);
|
||||||
using (var writer = new StreamWriter(responseStream, context.SelectedEncoding, bufferSize: 1024))
|
using (var writer = new StreamWriter(responseStream, context.SelectedEncoding, bufferSize: 1024))
|
||||||
{
|
{
|
||||||
await writer.WriteAsync(builder.ToString());
|
await writer.WriteAsync(builder.ToString());
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace FormatFilterWebSite
|
||||||
var actionReturn = context.Object as Product;
|
var actionReturn = context.Object as Product;
|
||||||
if (actionReturn != null)
|
if (actionReturn != null)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
context.SelectedContentType = contentType;
|
context.SelectedContentType = contentType;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ namespace FormatFilterWebSite
|
||||||
|
|
||||||
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
|
||||||
{
|
{
|
||||||
var response = context.ActionContext.HttpContext.Response;
|
var response = context.HttpContext.Response;
|
||||||
await response.WriteAsync(context.Object.ToString());
|
await response.WriteAsync(context.Object.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ namespace FormatterWebSite
|
||||||
|
|
||||||
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
|
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
|
||||||
{
|
{
|
||||||
var request = context.ActionContext.HttpContext.Request;
|
var request = context.HttpContext.Request;
|
||||||
MediaTypeHeaderValue requestContentType = null;
|
MediaTypeHeaderValue requestContentType = null;
|
||||||
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
|
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
|
||||||
var effectiveEncoding = SelectCharacterEncoding(requestContentType);
|
var effectiveEncoding = SelectCharacterEncoding(requestContentType);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue