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

View File

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

View File

@ -122,12 +122,22 @@ namespace Microsoft.AspNet.Mvc.Formatters
} }
var objectResult = context.Result as ObjectResult; var objectResult = context.Result as ObjectResult;
if (objectResult != null) if (objectResult == null)
{ {
var contentType = _options.FormatterMappings.GetMediaTypeMappingForFormat(format); return;
objectResult.ContentTypes.Clear();
objectResult.ContentTypes.Add(contentType);
} }
// 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 /> /// <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 // 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 mediaType = MediaTypeHeaderValue.Parse("application/json");
var mockObjects = new MockObjects("json", FormatSource.RouteData); var mockObjects = new MockObjects("json", FormatSource.RouteData);
var httpContext = new Mock<HttpContext>(); 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.ContainsKey("format")).Returns(true);
httpContext.Setup(c => c.Request.Query["format"]).Returns("xml"); httpContext.Setup(c => c.Request.Query["format"]).Returns("xml");
@ -106,7 +107,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
FormatSource place, FormatSource place,
string contentType) string contentType)
{ {
// Arrange // Arrange
var mediaType = MediaTypeHeaderValue.Parse(contentType); var mediaType = MediaTypeHeaderValue.Parse(contentType);
var mockObjects = new MockObjects(format, place); var mockObjects = new MockObjects(format, place);
@ -226,7 +227,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
// Act // Act
filter.OnResourceExecuting(resourceExecutingContext); filter.OnResourceExecuting(resourceExecutingContext);
// Assert // Assert
var actionResult = resourceExecutingContext.Result; var actionResult = resourceExecutingContext.Result;
Assert.IsType<HttpNotFoundResult>(actionResult); Assert.IsType<HttpNotFoundResult>(actionResult);
} }
@ -298,6 +299,73 @@ namespace Microsoft.AspNet.Mvc.Formatters
Assert.Equal(expected, filter.GetFormat(context)); 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( private static void AssertMediaTypesEqual(
MediaTypeHeaderValue expectedMediaType, MediaTypeHeaderValue expectedMediaType,
MediaTypeHeaderValue actualMediaType) MediaTypeHeaderValue actualMediaType)
@ -326,6 +394,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
{ {
var httpContext = new Mock<HttpContext>(); var httpContext = new Mock<HttpContext>();
httpContext.Setup(c => c.Request.Query.ContainsKey("format")).Returns(false); httpContext.Setup(c => c.Request.Query.ContainsKey("format")).Returns(false);
httpContext.Setup(c => c.Response).Returns(new Mock<HttpResponse>().Object);
MockHttpContext = httpContext.Object; MockHttpContext = httpContext.Object;
Initialize(httpContext, format, place); Initialize(httpContext, format, place);