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:
Ryan Nowak 2015-05-11 18:26:53 -07:00
parent fcf7b15c64
commit 39fe063aee
36 changed files with 402 additions and 370 deletions

View File

@ -2,33 +2,51 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Represents information used by an input formatter for
/// deserializing the request body into an object.
/// A context object used by an input formatter for deserializing the request body into an object.
/// </summary>
public class InputFormatterContext
{
/// <summary>
/// Creates a new instance of <see cref="InputFormatterContext"/>.
/// </summary>
public InputFormatterContext([NotNull] ActionContext actionContext,
[NotNull] Type modelType)
/// <param name="httpContext">
/// 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;
}
/// <summary>
/// Action context associated with the current call.
/// Gets the <see cref="Http.HttpContext"/> associated with the current operation.
/// </summary>
public ActionContext ActionContext { get; private set; }
public HttpContext HttpContext { get; private set; }
/// <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>
public Type ModelType { get; private set; }
}

View File

@ -3,6 +3,7 @@
using System;
using System.Text;
using Microsoft.AspNet.Http;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
@ -24,9 +25,9 @@ namespace Microsoft.AspNet.Mvc
public Type DeclaredType { get; set; }
/// <summary>
/// Action context associated with the current call.
/// Gets or sets the <see cref="HttpContext"/> context associated with the current operation.
/// </summary>
public ActionContext ActionContext { get; set; }
public HttpContext HttpContext { get; set; }
/// <summary>
/// The encoding which is chosen by the selected formatter.

View File

@ -101,7 +101,7 @@ namespace Microsoft.AspNet.Mvc
var formatterContext = new OutputFormatterContext()
{
ActionContext = context,
HttpContext = context.HttpContext,
DeclaredType = objectResult.DeclaredType,
Object = Value,
};
@ -125,7 +125,6 @@ namespace Microsoft.AspNet.Mvc
{
// If no formatter was provided, then run Conneg with the formatters configured in options.
var formatters = formatterContext
.ActionContext
.HttpContext
.RequestServices
.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
// 'global' one.
formatter = formatterContext
.ActionContext
.HttpContext
.RequestServices
.GetRequiredService<JsonOutputFormatter>();

View File

@ -49,7 +49,7 @@ namespace Microsoft.AspNet.Mvc
var formatterContext = new OutputFormatterContext()
{
DeclaredType = DeclaredType,
ActionContext = context,
HttpContext = context.HttpContext,
Object = Value,
StatusCode = StatusCode
};
@ -83,8 +83,7 @@ namespace Microsoft.AspNet.Mvc
OutputFormatterContext formatterContext,
IEnumerable<IOutputFormatter> formatters)
{
var logger = formatterContext.ActionContext.HttpContext.RequestServices
.GetRequiredService<ILogger<ObjectResult>>();
var logger = formatterContext.HttpContext.RequestServices.GetRequiredService<ILogger<ObjectResult>>();
// 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.
@ -108,7 +107,7 @@ namespace Microsoft.AspNet.Mvc
// which can write the type.
MediaTypeHeaderValue requestContentType = null;
MediaTypeHeaderValue.TryParse(
formatterContext.ActionContext.HttpContext.Request.ContentType,
formatterContext.HttpContext.Request.ContentType,
out requestContentType);
if (!sortedAcceptHeaderMediaTypes.Any() && requestContentType == null)
{
@ -240,17 +239,18 @@ namespace Microsoft.AspNet.Mvc
private IEnumerable<MediaTypeHeaderValue> GetSortedAcceptHeaderMediaTypes(
OutputFormatterContext formatterContext)
{
var request = formatterContext.ActionContext.HttpContext.Request;
var request = formatterContext.HttpContext.Request;
var incomingAcceptHeaderMediaTypes = request.GetTypedHeaders().Accept ?? new MediaTypeHeaderValue[] { };
// By default we want to ignore considering accept headers for content negotiation when
// they have a media type like */* in them. Browsers typically have these media types.
// In these cases we would want the first formatter in the list of output formatters to
// write the response. This default behavior can be changed through options, so checking here.
var options = formatterContext.ActionContext.HttpContext
.RequestServices
.GetRequiredService<IOptions<MvcOptions>>()
.Options;
var options = formatterContext
.HttpContext
.RequestServices
.GetRequiredService<IOptions<MvcOptions>>()
.Options;
var respectAcceptHeader = true;
if (options.RespectBrowserAcceptHeader == false

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc
public Task WriteAsync(OutputFormatterContext context)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
response.ContentLength = 0;
response.StatusCode = context.StatusCode ?? StatusCodes.Status204NoContent;
return Task.FromResult(true);

View File

@ -21,7 +21,7 @@ namespace Microsoft.AspNet.Mvc
/// <inheritdoc />
public Task WriteAsync(OutputFormatterContext context)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
response.StatusCode = StatusCodes.Status406NotAcceptable;
return Task.FromResult(true);
}

View File

@ -48,7 +48,7 @@ namespace Microsoft.AspNet.Mvc
return false;
}
var contentType = context.ActionContext.HttpContext.Request.ContentType;
var contentType = context.HttpContext.Request.ContentType;
MediaTypeHeaderValue requestContentType;
if (!MediaTypeHeaderValue.TryParse(contentType, out requestContentType))
{
@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Mvc
/// <inheritdoc />
public virtual async Task<object> ReadAsync(InputFormatterContext context)
{
var request = context.ActionContext.HttpContext.Request;
var request = context.HttpContext.Request;
if (request.ContentLength == 0)
{
return GetDefaultValueForType(context.ModelType);

View File

@ -52,7 +52,7 @@ namespace Microsoft.AspNet.Mvc
public override Task<object> ReadRequestBodyAsync([NotNull] InputFormatterContext context)
{
var type = context.ModelType;
var request = context.ActionContext.HttpContext.Request;
var request = context.HttpContext.Request;
MediaTypeHeaderValue requestContentType = null;
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc
errorHandler = (sender, e) =>
{
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
// Failure to do so can cause the exception to be rethrown at every recursive level and

View File

@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Mvc
public override Task WriteResponseBodyAsync(OutputFormatterContext context)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
var selectedEncoding = context.SelectedEncoding;
using (var writer = new HttpResponseStreamWriter(response.Body, selectedEncoding))

View File

@ -104,7 +104,7 @@ namespace Microsoft.AspNet.Mvc
/// <returns>The <see cref="Encoding"/> to use when reading the request or writing the response.</returns>
public virtual Encoding SelectCharacterEncoding([NotNull] OutputFormatterContext context)
{
var request = context.ActionContext.HttpContext.Request;
var request = context.HttpContext.Request;
var encoding = MatchAcceptCharacterEncoding(request.GetTypedHeaders().AcceptCharset);
if (encoding == null)
{
@ -195,7 +195,7 @@ namespace Microsoft.AspNet.Mvc
selectedMediaType.Charset = selectedEncoding.WebName;
context.SelectedContentType = context.SelectedContentType ?? selectedMediaType;
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
response.ContentType = selectedMediaType.ToString();
}

View File

@ -33,7 +33,7 @@ namespace Microsoft.AspNet.Mvc
{
using (var valueAsStream = ((Stream)context.Object))
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
if (context.SelectedContentType != null)
{

View File

@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc
return;
}
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
await response.WriteAsync(valueAsString, context.SelectedEncoding);
}

View File

@ -3,7 +3,6 @@
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.Framework.DependencyInjection;
@ -26,14 +25,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
/// <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 actionContext = requestServices.GetRequiredService<IScopedInstance<ActionContext>>().Value;
var formatters = requestServices.GetRequiredService<IScopedInstance<ActionBindingContext>>().Value.InputFormatters;
var httpContext = bindingContext.OperationBindingContext.HttpContext;
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));
if (formatter == null)

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
public async Task WriteAsync(OutputFormatterContext context)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
var responseMessage = context.Object as HttpResponseMessage;
if (responseMessage == null)
@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShim
{
response.StatusCode = (int)responseMessage.StatusCode;
var responseFeature = context.ActionContext.HttpContext.GetFeature<IHttpResponseFeature>();
var responseFeature = context.HttpContext.GetFeature<IHttpResponseFeature>();
if (responseFeature != null)
{
responseFeature.ReasonPhrase = responseMessage.ReasonPhrase;

View File

@ -94,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.Xml
/// <returns>Task which reads the input.</returns>
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.ActionContext.HttpContext.Request;
var request = context.HttpContext.Request;
MediaTypeHeaderValue requestContentType;
MediaTypeHeaderValue.TryParse(request.ContentType , out requestContentType);
@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.Xml
_dataAnnotationRequiredAttributeValidation.Validate(
type,
context.ActionContext.ModelState);
context.ModelState);
var serializer = GetCachedSerializer(type);

View File

@ -167,7 +167,7 @@ namespace Microsoft.AspNet.Mvc.Xml
var tempWriterSettings = WriterSettings.Clone();
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 xmlWriter = CreateXmlWriter(outputStream, tempWriterSettings))

View File

@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc.Xml
/// <returns>Task which reads the input.</returns>
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.ActionContext.HttpContext.Request;
var request = context.HttpContext.Request;
MediaTypeHeaderValue requestContentType;
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);

View File

@ -139,12 +139,12 @@ namespace Microsoft.AspNet.Mvc.Xml
/// <inheritdoc />
public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
var tempWriterSettings = WriterSettings.Clone();
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 xmlWriter = CreateXmlWriter(outputStream, tempWriterSettings))

View File

@ -357,7 +357,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
var context = new OutputFormatterContext()
{
ActionContext = actionContext,
HttpContext = actionContext.HttpContext,
Object = input,
DeclaredType = typeof(string)
};
@ -530,7 +530,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
new ActionDescriptor());
var formatterContext = new OutputFormatterContext()
{
ActionContext = tempActionContext,
HttpContext = tempActionContext.HttpContext,
Object = nonStringValue,
DeclaredType = nonStringValue.GetType()
};

View File

@ -38,8 +38,8 @@ namespace Microsoft.AspNet.Mvc
var formatter = new JsonInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes("content");
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(actionContext, typeof(string));
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(httpContext, new ModelStateDictionary(), typeof(string));
// Act
var result = formatter.CanRead(formatterContext);
@ -80,8 +80,8 @@ namespace Microsoft.AspNet.Mvc
var formatter = new JsonInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes);
var context = new InputFormatterContext(actionContext, type);
var httpContext = GetHttpContext(contentBytes);
var context = new InputFormatterContext(httpContext, new ModelStateDictionary(), type);
// Act
var model = await formatter.ReadAsync(context);
@ -98,9 +98,8 @@ namespace Microsoft.AspNet.Mvc
var formatter = new JsonInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes);
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(User));
var context = new InputFormatterContext(actionContext, metadata.ModelType);
var httpContext = GetHttpContext(contentBytes);
var context = new InputFormatterContext(httpContext, new ModelStateDictionary(), typeof(User));
// Act
var model = await formatter.ReadAsync(context);
@ -119,16 +118,18 @@ namespace Microsoft.AspNet.Mvc
var formatter = new JsonInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes);
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(User));
var context = new InputFormatterContext(actionContext, metadata.ModelType);
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
var context = new InputFormatterContext(httpContext, modelState, typeof(User));
// Act
var model = await formatter.ReadAsync(context);
// Assert
Assert.Equal("Could not convert string to decimal: not-an-age. Path 'Age', line 1, position 39.",
actionContext.ModelState["Age"].Errors[0].Exception.Message);
Assert.Equal(
"Could not convert string to decimal: not-an-age. Path 'Age', line 1, position 39.",
modelState["Age"].Errors[0].Exception.Message);
}
[Fact]
@ -139,19 +140,21 @@ namespace Microsoft.AspNet.Mvc
var formatter = new JsonInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes);
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(User));
var context = new InputFormatterContext(actionContext, metadata.ModelType);
actionContext.ModelState.MaxAllowedErrors = 3;
actionContext.ModelState.AddModelError("key1", "error1");
actionContext.ModelState.AddModelError("key2", "error2");
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
var context = new InputFormatterContext(httpContext, modelState, typeof(User));
modelState.MaxAllowedErrors = 3;
modelState.AddModelError("key1", "error1");
modelState.AddModelError("key2", "error2");
// Act
var model = await formatter.ReadAsync(context);
// Assert
Assert.False(actionContext.ModelState.ContainsKey("age"));
var error = Assert.Single(actionContext.ModelState[""].Errors);
Assert.False(modelState.ContainsKey("age"));
var error = Assert.Single(modelState[""].Errors);
Assert.IsType<TooManyModelErrorsException>(error.Exception);
}
@ -189,17 +192,18 @@ namespace Microsoft.AspNet.Mvc
// by default we ignore missing members, so here explicitly changing it
jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
var actionContext = GetActionContext(contentBytes, "application/json;charset=utf-8");
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(UserLogin));
var inputFormatterContext = new InputFormatterContext(actionContext, metadata.ModelType);
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8");
var inputFormatterContext = new InputFormatterContext(httpContext, modelState, typeof(UserLogin));
// Act
var obj = await jsonFormatter.ReadAsync(inputFormatterContext);
// 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);
}
@ -217,51 +221,24 @@ namespace Microsoft.AspNet.Mvc
MissingMemberHandling = MissingMemberHandling.Error
};
var actionContext = GetActionContext(contentBytes, "application/json;charset=utf-8");
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(UserLogin));
var inputFormatterContext = new InputFormatterContext(actionContext, metadata.ModelType);
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8");
var inputFormatterContext = new InputFormatterContext(httpContext, modelState, typeof(UserLogin));
// Act
var obj = await jsonFormatter.ReadAsync(inputFormatterContext);
// 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);
}
[Fact]
public async Task Validation_DoesNotHappen_ForNonRequired_ValueTypeProperties()
{
// 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")
private static HttpContext GetHttpContext(
byte[] contentBytes,
string contentType = "application/json")
{
var request = new Mock<HttpRequest>();
var headers = new Mock<IHeaderDictionary>();

View File

@ -62,11 +62,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
Assert.Equal(expectedOutput,
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
Assert.NotNull(body);
body.Position = 0;
var content = new StreamReader(body, Encoding.UTF8).ReadToEnd();
Assert.Equal(expectedOutput, content);
}
[Fact]
@ -93,11 +95,13 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
var body = outputFormatterContext.HttpContext.Response.Body;
var streamReader = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8);
Assert.Equal(expectedOutput, streamReader.ReadToEnd());
Assert.NotNull(body);
body.Position = 0;
var content = new StreamReader(body, Encoding.UTF8).ReadToEnd();
Assert.Equal(expectedOutput, content);
}
[Fact]
@ -155,12 +159,14 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
var encoding = CreateOrGetSupportedEncoding(formatter, encodingAsString, isDefaultEncoding);
var expectedData = encoding.GetBytes(formattedContent);
var memStream = new MemoryStream();
var body = new MemoryStream();
var actionContext = GetActionContext(MediaTypeHeaderValue.Parse(mediaType), body);
var outputFormatterContext = new OutputFormatterContext
{
Object = content,
DeclaredType = typeof(string),
ActionContext = GetActionContext(MediaTypeHeaderValue.Parse(mediaType), memStream),
HttpContext = actionContext.HttpContext,
SelectedEncoding = encoding
};
@ -168,7 +174,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
await formatter.WriteResponseBodyAsync(outputFormatterContext);
// Assert
var actualData = memStream.ToArray();
var actualData = body.ToArray();
Assert.Equal(expectedData, actualData);
}
@ -200,11 +206,12 @@ namespace Microsoft.AspNet.Mvc.Core.Test.Formatters
{
var mediaTypeHeaderValue = MediaTypeHeaderValue.Parse(contentType);
var actionContext = GetActionContext(mediaTypeHeaderValue, responseStream);
return new OutputFormatterContext
{
Object = outputValue,
DeclaredType = outputType,
ActionContext = GetActionContext(mediaTypeHeaderValue, responseStream),
HttpContext = actionContext.HttpContext,
SelectedEncoding = Encoding.GetEncoding(mediaTypeHeaderValue.Charset)
};
}

View File

@ -23,8 +23,9 @@ namespace Microsoft.AspNet.Mvc
var content = "[{\"op\":\"add\",\"path\":\"Customer/Name\",\"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes);
var context = new InputFormatterContext(actionContext, typeof(JsonPatchDocument<Customer>));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
var context = new InputFormatterContext(httpContext, modelState, typeof(JsonPatchDocument<Customer>));
// Act
var model = await formatter.ReadAsync(context);
@ -45,8 +46,9 @@ namespace Microsoft.AspNet.Mvc
"{\"op\": \"remove\", \"path\" : \"Customer/Name\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes);
var context = new InputFormatterContext(actionContext, typeof(JsonPatchDocument<Customer>));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
var context = new InputFormatterContext(httpContext, modelState, typeof(JsonPatchDocument<Customer>));
// Act
var model = await formatter.ReadAsync(context);
@ -72,8 +74,12 @@ namespace Microsoft.AspNet.Mvc
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(actionContext, typeof(JsonPatchDocument<Customer>));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(
httpContext,
modelState,
typeof(JsonPatchDocument<Customer>));
// Act
var result = formatter.CanRead(formatterContext);
@ -92,8 +98,9 @@ namespace Microsoft.AspNet.Mvc
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes, contentType: "application/json-patch+json");
var formatterContext = new InputFormatterContext(actionContext, modelType);
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/json-patch+json");
var formatterContext = new InputFormatterContext(httpContext, modelState, modelType);
// Act
var result = formatter.CanRead(formatterContext);
@ -113,25 +120,20 @@ namespace Microsoft.AspNet.Mvc
var content = "[{\"op\": \"add\", \"path\" : \"Customer/Name\", \"value\":\"John\"}]";
var contentBytes = Encoding.UTF8.GetBytes(content);
var actionContext = GetActionContext(contentBytes, contentType: "application/json-patch+json");
var context = new InputFormatterContext(actionContext, typeof(Customer));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/json-patch+json");
var context = new InputFormatterContext(httpContext, modelState, typeof(Customer));
// Act
var model = await formatter.ReadAsync(context);
// Assert
Assert.Contains(exceptionMessage, actionContext.ModelState[""].Errors[0].Exception.Message);
Assert.Contains(exceptionMessage, modelState[""].Errors[0].Exception.Message);
}
private static ActionContext GetActionContext(byte[] contentBytes,
string contentType = "application/json-patch+json")
{
return new ActionContext(GetHttpContext(contentBytes, contentType),
new AspNet.Routing.RouteData(),
new ActionDescriptor());
}
private static HttpContext GetHttpContext(byte[] contentBytes,
private static HttpContext GetHttpContext(
byte[] contentBytes,
string contentType = "application/json-patch+json")
{
var request = new Mock<HttpRequest>();

View File

@ -45,7 +45,7 @@ namespace Microsoft.AspNet.Mvc.Test
{
Object = value,
DeclaredType = typeToUse,
ActionContext = null,
HttpContext = null,
};
var contetType = useNonNullContentType ? MediaTypeHeaderValue.Parse("text/plain") : null;
var formatter = new HttpNoContentOutputFormatter();
@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Mvc.Test
{
Object = "Something non null.",
DeclaredType = declaredType,
ActionContext = null,
HttpContext = null,
};
var contetType = MediaTypeHeaderValue.Parse("text/plain");
var formatter = new HttpNoContentOutputFormatter();
@ -93,7 +93,7 @@ namespace Microsoft.AspNet.Mvc.Test
{
Object = value,
DeclaredType = typeof(string),
ActionContext = null,
HttpContext = null,
};
var contetType = MediaTypeHeaderValue.Parse("text/plain");
@ -117,7 +117,7 @@ namespace Microsoft.AspNet.Mvc.Test
var formatterContext = new OutputFormatterContext()
{
Object = null,
ActionContext = new ActionContext(defaultHttpContext, new RouteData(), new ActionDescriptor())
HttpContext = defaultHttpContext,
};
var formatter = new HttpNoContentOutputFormatter();
@ -137,7 +137,7 @@ namespace Microsoft.AspNet.Mvc.Test
var formatterContext = new OutputFormatterContext()
{
Object = null,
ActionContext = new ActionContext(defaultHttpContext, new RouteData(), new ActionDescriptor()),
HttpContext = defaultHttpContext,
StatusCode = StatusCodes.Status201Created
};

View File

@ -54,7 +54,7 @@ namespace Microsoft.AspNet.Mvc.Test
httpRequest.Headers["Accept-Charset"] = acceptCharsetHeaders;
httpRequest.ContentType = "application/acceptCharset;charset=" + requestEncoding;
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
var formatter = new TestOutputFormatter();
foreach (string supportedEncoding in supportedEncodings)
{
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc.Test
var formatterContext = new OutputFormatterContext()
{
Object = "someValue",
ActionContext = actionContext,
HttpContext = mockHttpContext.Object,
DeclaredType = typeof(string)
};
@ -85,8 +85,7 @@ namespace Microsoft.AspNet.Mvc.Test
var mockHttpContext = new Mock<HttpContext>();
var httpRequest = new DefaultHttpContext().Request;
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
formatterContext.ActionContext = actionContext;
formatterContext.HttpContext = mockHttpContext.Object;
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(
@ -108,8 +107,7 @@ namespace Microsoft.AspNet.Mvc.Test
var httpRequest = new DefaultHttpContext().Request;
mockHttpContext.SetupGet(o => o.Request).Returns(httpRequest);
mockHttpContext.SetupProperty(o => o.Response.ContentType);
var actionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor());
formatterContext.ActionContext = actionContext;
formatterContext.HttpContext = mockHttpContext.Object;
// Act
testFormatter.WriteResponseHeaders(formatterContext);
@ -130,10 +128,7 @@ namespace Microsoft.AspNet.Mvc.Test
var mediaType = new MediaTypeHeaderValue("image/png");
formatter.SupportedMediaTypes.Add(mediaType);
var formatterContext = new OutputFormatterContext();
formatterContext.ActionContext = new ActionContext(
new DefaultHttpContext(),
new RouteData(),
new ActionDescriptor());
formatterContext.HttpContext = new DefaultHttpContext();
// Act
await formatter.WriteAsync(formatterContext);

View File

@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc
{
Object = null,
DeclaredType = typeof(string),
ActionContext = new ActionContext(mockHttpContext.Object, new RouteData(), new ActionDescriptor()),
HttpContext = mockHttpContext.Object,
SelectedEncoding = encoding
};

View File

@ -143,7 +143,7 @@ namespace Microsoft.AspNet.Mvc.WebApiCompatShimTest
{
Object = outputValue,
DeclaredType = outputType,
ActionContext = new ActionContext(httpContext, routeData: null, actionDescriptor: null)
HttpContext = httpContext,
};
}
}

View File

@ -79,8 +79,9 @@ namespace Microsoft.AspNet.Mvc.Xml
var formatter = new XmlDataContractSerializerInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes("content");
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(actionContext, typeof(string));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(httpContext, modelState, typeof(string));
// Act
var result = formatter.CanRead(formatterContext);
@ -285,7 +286,7 @@ namespace Microsoft.AspNet.Mvc.Xml
// Assert
Assert.NotNull(model);
Assert.True(context.ActionContext.HttpContext.Request.Body.CanRead);
Assert.True(context.HttpContext.Request.Body.CanRead);
}
[Fact]
@ -328,8 +329,11 @@ namespace Microsoft.AspNet.Mvc.Xml
"<DummyClass><SampleInt>1000</SampleInt></DummyClass>");
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
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
@ -381,8 +385,10 @@ namespace Microsoft.AspNet.Mvc.Xml
var formatter = new XmlDataContractSerializerInputFormatter();
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
var actionContext = GetActionContext(contentBytes, contentType: "application/xml; charset=utf-16");
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");
var context = new InputFormatterContext(httpContext, modelState, typeof(TestLevelOne));
// Act
var model = await formatter.ReadAsync(context);
@ -530,10 +536,10 @@ namespace Microsoft.AspNet.Mvc.Xml
Assert.Equal(98052, model[0].Zipcode);
Assert.Equal(true, model[0].IsResidential);
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(1, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
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(true, model.IsResidential);
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(1, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
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(true, model.AddressProperty.IsResidential);
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(1, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
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(true, model.Addresses[0].IsResidential);
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(1, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
modelStateKey: typeof(Address).FullName,
actionContext: context.ActionContext,
expectedErrorMessages: new[]
typeof(Address).FullName,
context,
new[]
{
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), 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(true, model.IsResidential);
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(1, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
@ -710,7 +716,7 @@ namespace Microsoft.AspNet.Mvc.Xml
Assert.NotNull(model);
Assert.Equal(expectedModel.Year, model.Year);
Assert.Equal(expectedModel.ServicedYears, model.ServicedYears);
Assert.Empty(context.ActionContext.ModelState);
Assert.Empty(context.ModelState);
}
[Fact]
@ -745,7 +751,7 @@ namespace Microsoft.AspNet.Mvc.Xml
Assert.NotNull(model.CarInfoProperty);
Assert.Equal(expectedModel.CarInfoProperty.Year, model.CarInfoProperty.Year);
Assert.Equal(expectedModel.CarInfoProperty.ServicedYears, model.CarInfoProperty.ServicedYears);
Assert.Empty(context.ActionContext.ModelState);
Assert.Empty(context.ModelState);
}
[Fact]
@ -781,10 +787,10 @@ namespace Microsoft.AspNet.Mvc.Xml
Assert.Equal(expectedModel.Manager.Name, model.Manager.Name);
Assert.Null(model.Manager.Manager);
Assert.Equal(1, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(1, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Employee).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
@ -810,7 +816,7 @@ namespace Microsoft.AspNet.Mvc.Xml
Assert.NotNull(model);
Assert.Equal(10, model.Id);
Assert.Equal(true, model.SupportsVirtualization);
Assert.Empty(context.ActionContext.ModelState);
Assert.Empty(context.ModelState);
}
[Fact]
@ -833,7 +839,7 @@ namespace Microsoft.AspNet.Mvc.Xml
Assert.Equal(1, model.Count);
Assert.Equal(10, model[0].Id);
Assert.Equal(true, model[0].SupportsVirtualization);
Assert.Empty(context.ActionContext.ModelState);
Assert.Empty(context.ModelState);
}
[Fact]
@ -855,10 +861,10 @@ namespace Microsoft.AspNet.Mvc.Xml
Assert.NotNull(model);
Assert.Equal(10, model.Id);
Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(2, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Product).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
@ -866,7 +872,7 @@ namespace Microsoft.AspNet.Mvc.Xml
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
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("Phone", model[0].Name);
Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(2, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Product).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
@ -906,7 +912,7 @@ namespace Microsoft.AspNet.Mvc.Xml
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Address.Zipcode), typeof(Address).FullName),
@ -931,10 +937,10 @@ namespace Microsoft.AspNet.Mvc.Xml
// Assert
Assert.Null(model);
Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(3, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
@ -943,7 +949,7 @@ namespace Microsoft.AspNet.Mvc.Xml
AssertModelStateErrorMessages(
typeof(Employee).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Employee.Id), typeof(Employee).FullName)
@ -951,7 +957,7 @@ namespace Microsoft.AspNet.Mvc.Xml
AssertModelStateErrorMessages(
typeof(Product).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Product.Id), typeof(Product).FullName)
@ -976,17 +982,17 @@ namespace Microsoft.AspNet.Mvc.Xml
// Assert
Assert.Null(model);
Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(3, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(School).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(School.Id), typeof(School).FullName)
});
AssertModelStateErrorMessages(
typeof(Website).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Website.Id), typeof(Website).FullName)
@ -994,7 +1000,7 @@ namespace Microsoft.AspNet.Mvc.Xml
AssertModelStateErrorMessages(
typeof(Student).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Student.Id), typeof(Student).FullName)
@ -1019,10 +1025,10 @@ namespace Microsoft.AspNet.Mvc.Xml
// Assert
Assert.Null(model);
Assert.Equal(2, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(2, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Point).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
@ -1030,7 +1036,7 @@ namespace Microsoft.AspNet.Mvc.Xml
});
AssertModelStateErrorMessages(
typeof(Address).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Address.IsResidential), typeof(Address).FullName),
@ -1056,10 +1062,10 @@ namespace Microsoft.AspNet.Mvc.Xml
// Assert
Assert.Null(model);
Assert.Equal(3, context.ActionContext.ModelState.Keys.Count);
Assert.Equal(3, context.ModelState.Keys.Count);
AssertModelStateErrorMessages(
typeof(Point).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(requiredErrorMessageFormat, nameof(Point.X), typeof(Point).FullName),
@ -1067,7 +1073,7 @@ namespace Microsoft.AspNet.Mvc.Xml
});
AssertModelStateErrorMessages(
typeof(GpsCoordinate).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(
@ -1081,7 +1087,7 @@ namespace Microsoft.AspNet.Mvc.Xml
});
AssertModelStateErrorMessages(
typeof(ValueTypePropertiesModel).FullName,
context.ActionContext,
context,
expectedErrorMessages: new[]
{
string.Format(
@ -1105,11 +1111,11 @@ namespace Microsoft.AspNet.Mvc.Xml
private void AssertModelStateErrorMessages(
string modelStateKey,
ActionContext actionContext,
InputFormatterContext context,
IEnumerable<string> expectedErrorMessages)
{
ModelState modelState;
actionContext.ModelState.TryGetValue(modelStateKey, out modelState);
context.ModelState.TryGetValue(modelStateKey, out modelState);
Assert.NotNull(modelState);
Assert.NotEmpty(modelState.Errors);
@ -1140,20 +1146,13 @@ namespace Microsoft.AspNet.Mvc.Xml
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
{
var actionContext = GetActionContext(contentBytes);
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType);
return new InputFormatterContext(actionContext, metadata.ModelType);
var httpContext = GetHttpContext(contentBytes);
return new InputFormatterContext(httpContext, new ModelStateDictionary(), modelType);
}
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/xml")
private static HttpContext GetHttpContext(
byte[] contentBytes,
string contentType = "application/xml")
{
var request = new Mock<HttpRequest>();
var headers = new Mock<IHeaderDictionary>();

View File

@ -102,12 +102,11 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal(expectedOutput,
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
@ -158,17 +157,22 @@ namespace Microsoft.AspNet.Mvc.Xml
// Assert
Assert.Same(writerSettings, formatter.WriterSettings);
var responseStream = formatterContext.ActionContext.HttpContext.Response.Body;
Assert.NotNull(responseStream);
responseStream.Position = 0;
var actualOutput = new StreamReader(responseStream, Encoding.UTF8).ReadToEnd();
XmlAssert.Equal(expectedOutput, actualOutput);
var body = formatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task WriteAsync_WritesSimpleTypes()
{
// Arrange
var expectedOutput =
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<SampleInt>10</SampleInt></DummyClass>";
var sampleInput = new DummyClass { SampleInt = 10 };
var formatter = new XmlDataContractSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
@ -177,18 +181,23 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal("<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<SampleInt>10</SampleInt></DummyClass>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task WriteAsync_WritesComplexTypes()
{
// 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
{
SampleString = "TestString",
@ -205,24 +214,26 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal("<TestLevelTwo xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<SampleString>TestString</SampleString>" +
"<TestOne><SampleInt>10</SampleInt><sampleString>TestLevelOne string</sampleString>" +
"</TestOne></TestLevelTwo>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task WriteAsync_WritesOnModifiedWriterSettings()
{
// 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 outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
var formatter = new XmlDataContractSerializerOutputFormatter(
new System.Xml.XmlWriterSettings
new XmlWriterSettings
{
OmitXmlDeclaration = false,
CloseOutput = false
@ -232,19 +243,22 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<SampleInt>10</SampleInt></DummyClass>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
Encoding.UTF8).ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task WriteAsync_WritesUTF16Output()
{
// 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 outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType(),
"application/xml; charset=utf-16");
@ -255,19 +269,21 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<SampleInt>10</SampleInt></DummyClass>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
Encodings.UTF16EncodingLittleEndian).ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task WriteAsync_WritesIndentedOutput()
{
// 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 formatter = new XmlDataContractSerializerOutputFormatter();
formatter.WriterSettings.Indent = true;
@ -277,13 +293,11 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
var outputString = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
Encoding.UTF8).ReadToEnd();
XmlAssert.Equal("<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"\r\n <SampleInt>10</SampleInt>\r\n</DummyClass>",
outputString);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
@ -298,8 +312,8 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
var body = outputFormatterContext.HttpContext.Response.Body;
Assert.True(body.CanRead);
}
[Fact]
@ -310,7 +324,7 @@ namespace Microsoft.AspNet.Mvc.Xml
var formatter = new XmlDataContractSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
var response = outputFormatterContext.ActionContext.HttpContext.Response;
var response = outputFormatterContext.HttpContext.Response;
response.Body = FlushReportingStream.GetThrowingStream();
// Act & Assert
@ -447,11 +461,11 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
var actualOutput = new StreamReader(
outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8).ReadToEnd();
XmlAssert.Equal(expectedOutput, actualOutput);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
@ -491,11 +505,11 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
var actualOutput = new StreamReader(
outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8).ReadToEnd();
XmlAssert.Equal(expectedOutput, actualOutput);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
@ -535,11 +549,11 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
var actualOutput = new StreamReader(
outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8).ReadToEnd();
XmlAssert.Equal(expectedOutput, actualOutput);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
@ -549,23 +563,26 @@ namespace Microsoft.AspNet.Mvc.Xml
{
Object = outputValue,
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 headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
request.Setup(r => r.ContentType).Returns(contentType);
request.SetupGet(r => r.Headers).Returns(headers);
var response = new Mock<HttpResponse>();
response.SetupGet(f => f.Body).Returns(new MemoryStream());
var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.Request).Returns(request.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

View File

@ -56,8 +56,10 @@ namespace Microsoft.AspNet.Mvc.Xml
var formatter = new XmlSerializerInputFormatter();
var contentBytes = Encoding.UTF8.GetBytes("content");
var actionContext = GetActionContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(actionContext, typeof(string));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
var formatterContext = new InputFormatterContext(httpContext, modelState, typeof(string));
// Act
var result = formatter.CanRead(formatterContext);
@ -292,7 +294,7 @@ namespace Microsoft.AspNet.Mvc.Xml
// Assert
Assert.NotNull(model);
Assert.True(context.ActionContext.HttpContext.Request.Body.CanRead);
Assert.True(context.HttpContext.Request.Body.CanRead);
}
[Fact]
@ -337,8 +339,11 @@ namespace Microsoft.AspNet.Mvc.Xml
"<DummyClass><SampleInt>1000</SampleInt></DummyClass>");
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
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
@ -392,8 +397,9 @@ namespace Microsoft.AspNet.Mvc.Xml
var formatter = new XmlSerializerInputFormatter();
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
var actionContext = GetActionContext(contentBytes, contentType: "application/xml; charset=utf-16");
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");
var context = new InputFormatterContext(httpContext, modelState, typeof(TestLevelOne));
// Act
var model = await formatter.ReadAsync(context);
@ -410,21 +416,13 @@ namespace Microsoft.AspNet.Mvc.Xml
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
{
var actionContext = GetActionContext(contentBytes);
var metadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType);
return new InputFormatterContext(actionContext, metadata.ModelType);
var httpContext = GetHttpContext(contentBytes);
return new InputFormatterContext(httpContext, new ModelStateDictionary(), modelType);
}
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/xml")
private static HttpContext GetHttpContext(
byte[] contentBytes,
string contentType = "application/xml")
{
var request = new Mock<HttpRequest>();
var headers = new Mock<IHeaderDictionary>();

View File

@ -60,12 +60,11 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal(expectedOutput,
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
@ -115,18 +114,21 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(formatterContext);
// Assert
Assert.Same(writerSettings, formatter.WriterSettings);
var responseStream = formatterContext.ActionContext.HttpContext.Response.Body;
Assert.NotNull(responseStream);
responseStream.Position = 0;
var actualOutput = new StreamReader(responseStream, Encoding.UTF8).ReadToEnd();
XmlAssert.Equal(expectedOutput, actualOutput);
var body = formatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task XmlSerializerOutputFormatterWritesSimpleTypes()
{
// 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 formatter = new XmlSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
@ -135,19 +137,23 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.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>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task XmlSerializerOutputFormatterWritesComplexTypes()
{
// 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
{
SampleString = "TestString",
@ -164,20 +170,22 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.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>" +
"<TestOne><sampleString>TestLevelOne string</sampleString>" +
"<SampleInt>10</SampleInt></TestOne></TestLevelTwo>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task XmlSerializerOutputFormatterWritesOnModifiedWriterSettings()
{
// 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 outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
var formatter = new XmlSerializerOutputFormatter(
@ -191,19 +199,22 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal("<?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>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
.ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task XmlSerializerOutputFormatterWritesUTF16Output()
{
// 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 outputFormatterContext =
GetOutputFormatterContext(sampleInput, sampleInput.GetType(), "application/xml; charset=utf-16");
@ -214,19 +225,21 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
XmlAssert.Equal("<?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>",
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
Encodings.UTF16EncodingLittleEndian).ReadToEnd());
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
public async Task XmlSerializerOutputFormatterWritesIndentedOutput()
{
// 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 formatter = new XmlSerializerOutputFormatter();
formatter.WriterSettings.Indent = true;
@ -236,13 +249,11 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
var outputString = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
Encoding.UTF8).ReadToEnd();
XmlAssert.Equal("<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>",
outputString);
var body = outputFormatterContext.HttpContext.Response.Body;
body.Position = 0;
var content = new StreamReader(body).ReadToEnd();
XmlAssert.Equal(expectedOutput, content);
}
[Fact]
@ -257,8 +268,8 @@ namespace Microsoft.AspNet.Mvc.Xml
await formatter.WriteAsync(outputFormatterContext);
// Assert
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
Assert.NotNull(outputFormatterContext.HttpContext.Response.Body);
Assert.True(outputFormatterContext.HttpContext.Response.Body.CanRead);
}
public static IEnumerable<object[]> TypesForCanWriteResult
@ -304,7 +315,7 @@ namespace Microsoft.AspNet.Mvc.Xml
var formatter = new XmlSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
var response = outputFormatterContext.ActionContext.HttpContext.Response;
var response = outputFormatterContext.HttpContext.Response;
response.Body = FlushReportingStream.GetThrowingStream();
// Act & Assert
@ -346,30 +357,35 @@ namespace Microsoft.AspNet.Mvc.Xml
}
}
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
string contentType = "application/xml; charset=utf-8")
private OutputFormatterContext GetOutputFormatterContext(
object outputValue,
Type outputType,
string contentType = "application/xml; charset=utf-8")
{
return new OutputFormatterContext
{
Object = outputValue,
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 headers = new HeaderDictionary(new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase));
headers["Accept-Charset"] = MediaTypeHeaderValue.Parse(contentType).Charset;
request.Setup(r => r.ContentType).Returns(contentType);
request.SetupGet(r => r.Headers).Returns(headers);
var response = new Mock<HttpResponse>();
response.SetupGet(f => f.Body).Returns(new MemoryStream());
var httpContext = new Mock<HttpContext>();
httpContext.SetupGet(c => c.Request).Returns(request.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

View File

@ -35,7 +35,7 @@ namespace ContentNegotiationWebSite
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
response.ContentType = ContentType + ";charset=utf-8";
await response.WriteAsync(context.Object.ToString());
}

View File

@ -33,7 +33,7 @@ namespace ContentNegotiationWebSite
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";
await response.WriteAsync(context.Object as string);
}

View File

@ -39,7 +39,7 @@ namespace ContentNegotiationWebSite
builder.AppendLine();
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))
{
await writer.WriteAsync(builder.ToString());

View File

@ -42,7 +42,7 @@ namespace ContentNegotiationWebSite
builder.AppendLine();
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))
{
await writer.WriteAsync(builder.ToString());

View File

@ -27,7 +27,7 @@ namespace FormatFilterWebSite
var actionReturn = context.Object as Product;
if (actionReturn != null)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
context.SelectedContentType = contentType;
return true;
}
@ -37,7 +37,7 @@ namespace FormatFilterWebSite
public override async Task WriteResponseBodyAsync(OutputFormatterContext context)
{
var response = context.ActionContext.HttpContext.Response;
var response = context.HttpContext.Response;
await response.WriteAsync(context.Object.ToString());
}
}

View File

@ -19,7 +19,7 @@ namespace FormatterWebSite
public override Task<object> ReadRequestBodyAsync(InputFormatterContext context)
{
var request = context.ActionContext.HttpContext.Request;
var request = context.HttpContext.Request;
MediaTypeHeaderValue requestContentType = null;
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
var effectiveEncoding = SelectCharacterEncoding(requestContentType);