FormatFilter overrides content type set explicitly by the developer

This commit is contained in:
Kiran Challa 2015-12-28 15:51:18 -08:00
parent aab051a20f
commit 7a955bcbc0
4 changed files with 91 additions and 9 deletions

View File

@ -15,7 +15,7 @@ namespace FormatFilterSample.Web
// Set up application services
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
var mvcBuilder = services.AddMvc(options =>
{
var formatFilter = new FormatFilterAttribute();
options.Filters.Add(formatFilter);
@ -28,6 +28,8 @@ namespace FormatFilterSample.Web
"custom",
MediaTypeHeaderValue.Parse("application/custom"));
});
mvcBuilder.AddXmlDataContractSerializerFormatters();
}
public void Configure(IApplicationBuilder app)

View File

@ -7,6 +7,7 @@
},
"dependencies": {
"Microsoft.AspNet.Mvc": "6.0.0-*",
"Microsoft.AspNet.Mvc.Formatters.Xml": "6.0.0-*",
"Microsoft.AspNet.Server.Kestrel": "1.0.0-*"
},
"frameworks": {

View File

@ -122,12 +122,22 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
var objectResult = context.Result as ObjectResult;
if (objectResult != null)
if (objectResult == null)
{
var contentType = _options.FormatterMappings.GetMediaTypeMappingForFormat(format);
objectResult.ContentTypes.Clear();
objectResult.ContentTypes.Add(contentType);
return;
}
// If the action sets a single content type, then its takes precedence over the user
// supplied content type based on format mapping.
if ((objectResult.ContentTypes != null && objectResult.ContentTypes.Count == 1) ||
!string.IsNullOrEmpty(context.HttpContext.Response.ContentType))
{
return;
}
var contentType = _options.FormatterMappings.GetMediaTypeMappingForFormat(format);
objectResult.ContentTypes.Clear();
objectResult.ContentTypes.Add(contentType);
}
/// <inheritdoc />

View File

@ -60,12 +60,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
// If the format is present in both route and query data, the one in route data wins
// Arrange
// Arrange
var mediaType = MediaTypeHeaderValue.Parse("application/json");
var mockObjects = new MockObjects("json", FormatSource.RouteData);
var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.Response).Returns(new Mock<HttpResponse>().Object);
// Query contains xml
// Query contains xml
httpContext.Setup(c => c.Request.Query.ContainsKey("format")).Returns(true);
httpContext.Setup(c => c.Request.Query["format"]).Returns("xml");
@ -106,7 +107,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
FormatSource place,
string contentType)
{
// Arrange
// Arrange
var mediaType = MediaTypeHeaderValue.Parse(contentType);
var mockObjects = new MockObjects(format, place);
@ -226,7 +227,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Act
filter.OnResourceExecuting(resourceExecutingContext);
// Assert
// Assert
var actionResult = resourceExecutingContext.Result;
Assert.IsType<HttpNotFoundResult>(actionResult);
}
@ -298,6 +299,73 @@ namespace Microsoft.AspNet.Mvc.Formatters
Assert.Equal(expected, filter.GetFormat(context));
}
[Fact]
public void FormatFilter_ExplicitContentType_SetOnObjectResult_TakesPrecedence()
{
// Arrange
var mediaType = MediaTypeHeaderValue.Parse("application/foo");
var mockObjects = new MockObjects("json", FormatSource.QueryData);
var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.Response).Returns(new Mock<HttpResponse>().Object);
httpContext.Setup(c => c.Request.Query["format"]).Returns("json");
var actionContext = new ActionContext(httpContext.Object, new RouteData(), new ActionDescriptor());
var objectResult = new ObjectResult("Hello!");
objectResult.ContentTypes.Add(new MediaTypeHeaderValue("application/foo"));
var resultExecutingContext = new ResultExecutingContext(
actionContext,
new IFilterMetadata[] { },
objectResult,
controller: new object());
var resourceExecutingContext = new ResourceExecutingContext(
actionContext,
new IFilterMetadata[] { });
var filter = new FormatFilter(mockObjects.OptionsManager);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
filter.OnResultExecuting(resultExecutingContext);
// Assert
var result = Assert.IsType<ObjectResult>(resultExecutingContext.Result);
Assert.Equal(1, result.ContentTypes.Count);
AssertMediaTypesEqual(mediaType, result.ContentTypes[0]);
}
[Fact]
public void FormatFilter_ExplicitContentType_SetOnResponse_TakesPrecedence()
{
// Arrange
var mediaType = MediaTypeHeaderValue.Parse("application/foo");
var mockObjects = new MockObjects("json", FormatSource.QueryData);
var response = new Mock<HttpResponse>();
response.Setup(r => r.ContentType).Returns("application/foo");
var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.Response).Returns(response.Object);
httpContext.Setup(c => c.Request.Query["format"]).Returns("json");
var actionContext = new ActionContext(httpContext.Object, new RouteData(), new ActionDescriptor());
var resultExecutingContext = new ResultExecutingContext(
actionContext,
new IFilterMetadata[] { },
new ObjectResult("Hello!"),
controller: new object());
var resourceExecutingContext = new ResourceExecutingContext(
actionContext,
new IFilterMetadata[] { });
var filter = new FormatFilter(mockObjects.OptionsManager);
// Act
filter.OnResourceExecuting(resourceExecutingContext);
filter.OnResultExecuting(resultExecutingContext);
// Assert
var result = Assert.IsType<ObjectResult>(resultExecutingContext.Result);
Assert.Equal(0, result.ContentTypes.Count);
}
private static void AssertMediaTypesEqual(
MediaTypeHeaderValue expectedMediaType,
MediaTypeHeaderValue actualMediaType)
@ -326,6 +394,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.Request.Query.ContainsKey("format")).Returns(false);
httpContext.Setup(c => c.Response).Returns(new Mock<HttpResponse>().Object);
MockHttpContext = httpContext.Object;
Initialize(httpContext, format, place);