[Fixes 7139] Add format filter mapping for xml formatters
This commit is contained in:
parent
00c6b53b06
commit
2aae8774f6
|
|
@ -80,7 +80,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Json.Internal
|
|||
options,
|
||||
_jsonOptions));
|
||||
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json"));
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValues.ApplicationJson);
|
||||
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(IJsonPatchDocument)));
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(JToken)));
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|||
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
|
||||
{
|
||||
|
|
@ -42,6 +43,16 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
|
|||
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter(_loggerFactory));
|
||||
options.InputFormatters.Add(new XmlDataContractSerializerInputFormatter(options));
|
||||
|
||||
// Do not override any user mapping
|
||||
var key = "xml";
|
||||
var mapping = options.FormatterMappings.GetMediaTypeMappingForFormat(key);
|
||||
if (string.IsNullOrEmpty(mapping))
|
||||
{
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat(
|
||||
key,
|
||||
MediaTypeHeaderValues.ApplicationXml);
|
||||
}
|
||||
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider("System.Xml.Linq.XObject"));
|
||||
options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider("System.Xml.XmlNode"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
|
||||
{
|
||||
|
|
@ -35,6 +36,16 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
|
|||
/// <param name="options">The <see cref="MvcOptions"/>.</param>
|
||||
public void Configure(MvcOptions options)
|
||||
{
|
||||
// Do not override any user mapping
|
||||
var key = "xml";
|
||||
var mapping = options.FormatterMappings.GetMediaTypeMappingForFormat(key);
|
||||
if (string.IsNullOrEmpty(mapping))
|
||||
{
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat(
|
||||
key,
|
||||
MediaTypeHeaderValues.ApplicationXml);
|
||||
}
|
||||
|
||||
options.OutputFormatters.Add(new XmlSerializerOutputFormatter(_loggerFactory));
|
||||
options.InputFormatters.Add(new XmlSerializerInputFormatter(options));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
|
||||
{
|
||||
public class MvcXmlDataContractSerializerMvcOptionsSetupTest
|
||||
{
|
||||
[Fact]
|
||||
public void AddsFormatterMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new MvcXmlDataContractSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
optionsSetup.Configure(options);
|
||||
|
||||
// Assert
|
||||
var mappedContentType = options.FormatterMappings.GetMediaTypeMappingForFormat("xml");
|
||||
Assert.Equal("application/xml", mappedContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesNotOverrideExistingMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new MvcXmlDataContractSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("xml", "text/xml");
|
||||
|
||||
// Act
|
||||
optionsSetup.Configure(options);
|
||||
|
||||
// Assert
|
||||
var mappedContentType = options.FormatterMappings.GetMediaTypeMappingForFormat("xml");
|
||||
Assert.Equal("text/xml", mappedContentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
|
||||
{
|
||||
public class MvcXmlSerializerMvcOptionsSetupTest
|
||||
{
|
||||
[Fact]
|
||||
public void AddsFormatterMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new MvcXmlSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
optionsSetup.Configure(options);
|
||||
|
||||
// Assert
|
||||
var mappedContentType = options.FormatterMappings.GetMediaTypeMappingForFormat("xml");
|
||||
Assert.Equal("application/xml", mappedContentType);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DoesNotOverrideExistingMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new MvcXmlSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("xml", "text/xml");
|
||||
|
||||
// Act
|
||||
optionsSetup.Configure(options);
|
||||
|
||||
// Assert
|
||||
var mappedContentType = options.FormatterMappings.GetMediaTypeMappingForFormat("xml");
|
||||
Assert.Equal("text/xml", mappedContentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -450,13 +450,12 @@ END:VCARD
|
|||
[Fact]
|
||||
public async Task ProducesAttribute_And_FormatFilterAttribute_Conflicting()
|
||||
{
|
||||
// Arrange
|
||||
var expectedContentType = MediaTypeHeaderValue.Parse("application/json");
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync("http://localhost/FormatFilter/MethodWithFormatFilter.json");
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync(
|
||||
"http://localhost/FormatFilter/ProducesTakesPrecedenceOverUserSuppliedFormatMethod?format=json");
|
||||
|
||||
// Assert
|
||||
// Explicit content type set by the developer takes precedence over the format requested by the end user
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +463,8 @@ END:VCARD
|
|||
public async Task ProducesAttribute_And_FormatFilterAttribute_Collaborating()
|
||||
{
|
||||
// Arrange & Act
|
||||
var response = await Client.GetAsync("http://localhost/FormatFilter/MethodWithFormatFilter");
|
||||
var response = await Client.GetAsync(
|
||||
"http://localhost/FormatFilter/ProducesTakesPrecedenceOverUserSuppliedFormatMethod");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
|
@ -508,5 +508,24 @@ END:VCARD
|
|||
var contact = xmlDeserializer.ReadObject(bodyStream) as Contact;
|
||||
Assert.Equal("Jason Ecsemelle", contact.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FormatFilter_XmlAsFormat_ReturnsXml()
|
||||
{
|
||||
// Arrange
|
||||
var expectedBody = "<FormatFilterController.Customer xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\""
|
||||
+ " xmlns=\"http://schemas.datacontract.org/2004/07/BasicWebSite.Controllers.ContentNegotiation\">"
|
||||
+ "<Name>John</Name></FormatFilterController.Customer>";
|
||||
|
||||
// Act
|
||||
var response = await Client.GetAsync(
|
||||
"http://localhost/FormatFilter/CustomerInfo?format=xml");
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("application/xml; charset=utf-8", response.Content.Headers.ContentType.ToString());
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.Equal(expectedBody, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,24 +7,39 @@ using Microsoft.AspNetCore.Mvc.Filters;
|
|||
|
||||
namespace BasicWebSite.Controllers.ContentNegotiation
|
||||
{
|
||||
[Produces("application/FormatFilterController")]
|
||||
public class FormatFilterController : Controller
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var result = context.Result as ObjectResult;
|
||||
if (result != null)
|
||||
{
|
||||
result.Formatters.Add(new CustomFormatter("application/FormatFilterController"));
|
||||
}
|
||||
|
||||
base.OnActionExecuted(context);
|
||||
}
|
||||
|
||||
[Produces("application/FormatFilterController")]
|
||||
[FormatFilter]
|
||||
public string MethodWithFormatFilter()
|
||||
[CustomFormatterActionFilter]
|
||||
public string ProducesTakesPrecedenceOverUserSuppliedFormatMethod()
|
||||
{
|
||||
return "MethodWithFormatFilter";
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[FormatFilter]
|
||||
public Customer CustomerInfo()
|
||||
{
|
||||
return new Customer() { Name = "John" };
|
||||
}
|
||||
|
||||
private class CustomFormatterActionFilter : ActionFilterAttribute
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var result = context.Result as ObjectResult;
|
||||
if (result != null)
|
||||
{
|
||||
result.Formatters.Add(new CustomFormatter("application/FormatFilterController"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Customer
|
||||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue