Use InputFormatterException for another case (#6316)
- #4917 nits: - test `ExceptionPolicy` logic in an input formatter - remove old Mono workarounds in `SerializaterErrorTests` - fix typo in `SerializableErrorTests` (not using theory data)
This commit is contained in:
parent
c2df506894
commit
be7dfa30af
|
|
@ -159,9 +159,19 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
||||||
}
|
}
|
||||||
// XmlSerializer wraps actual exceptions (like FormatException or XmlException) into an InvalidOperationException
|
// XmlSerializer wraps actual exceptions (like FormatException or XmlException) into an InvalidOperationException
|
||||||
// https://github.com/dotnet/corefx/blob/master/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs#L652
|
// https://github.com/dotnet/corefx/blob/master/src/System.Private.Xml/src/System/Xml/Serialization/XmlSerializer.cs#L652
|
||||||
catch (InvalidOperationException exception) when (exception.InnerException is FormatException || exception.InnerException is XmlException)
|
catch (InvalidOperationException exception) when (exception.InnerException != null &&
|
||||||
|
exception.InnerException.InnerException == null &&
|
||||||
|
string.Equals("Microsoft.GeneratedCode", exception.InnerException.Source, StringComparison.InvariantCulture))
|
||||||
{
|
{
|
||||||
throw new InputFormatterException(Resources.ErrorDeserializingInputData, exception);
|
// Know this was an XML parsing error because the inner Exception was thrown in the (generated)
|
||||||
|
// assembly the XmlSerializer uses for parsing. The problem did not arise lower in the stack i.e. it's
|
||||||
|
// not (for example) an out-of-memory condition.
|
||||||
|
throw new InputFormatterException(Resources.ErrorDeserializingInputData, exception.InnerException);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException exception) when (exception.InnerException is FormatException ||
|
||||||
|
exception.InnerException is XmlException)
|
||||||
|
{
|
||||||
|
throw new InputFormatterException(Resources.ErrorDeserializingInputData, exception.InnerException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -839,8 +839,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
||||||
_throwNonInputFormatterException = throwNonInputFormatterException;
|
_throwNonInputFormatterException = throwNonInputFormatterException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override InputFormatterExceptionPolicy ExceptionPolicy => InputFormatterExceptionPolicy.AllExceptions;
|
|
||||||
|
|
||||||
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
|
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
|
||||||
{
|
{
|
||||||
if (_throwNonInputFormatterException)
|
if (_throwNonInputFormatterException)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,6 @@ using System.Net.Http.Headers;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Mvc.Formatters.Xml;
|
using Microsoft.AspNetCore.Mvc.Formatters.Xml;
|
||||||
using Microsoft.AspNetCore.Testing;
|
|
||||||
using Microsoft.AspNetCore.Testing.xunit;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
|
|
@ -22,22 +20,15 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
|
|
||||||
public HttpClient Client { get; }
|
public HttpClient Client { get; }
|
||||||
|
|
||||||
public static TheoryData AcceptHeadersData
|
public static TheoryData<string> AcceptHeadersData
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var data = new TheoryData<string>
|
return new TheoryData<string>
|
||||||
{
|
{
|
||||||
|
"application/xml-dcs",
|
||||||
"application/xml-xmlser"
|
"application/xml-xmlser"
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mono issue - https://github.com/aspnet/External/issues/18
|
|
||||||
if (!TestPlatformHelper.IsMono)
|
|
||||||
{
|
|
||||||
data.Add("application/xml-dcs");
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,19 +53,16 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
XmlAssert.Equal(expectedXml, responseData);
|
XmlAssert.Equal(expectedXml, responseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalTheory]
|
[Theory]
|
||||||
// Mono issue - https://github.com/aspnet/External/issues/18
|
[MemberData(nameof(AcceptHeadersData))]
|
||||||
// XmlSerializer test is disabled Mono.Xml2.XmlTextReader.ReadText is unable to read the XML.
|
|
||||||
// This is fixed in mono 4.3.0.
|
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
|
||||||
[InlineData("application/xml-xmlser")]
|
|
||||||
[InlineData("application/xml-dcs")]
|
|
||||||
public async Task PostedSerializableError_IsBound(string acceptHeader)
|
public async Task PostedSerializableError_IsBound(string acceptHeader)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var expectedXml = "<Error><key1>key1-error</key1><key2>The input was not valid.</key2></Error>";
|
var expectedXml = "<Error><key1>key1-error</key1><key2>The input was not valid.</key2></Error>";
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/SerializableError/LogErrors");
|
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/SerializableError/LogErrors")
|
||||||
request.Content = new StringContent(expectedXml, Encoding.UTF8, acceptHeader);
|
{
|
||||||
|
Content = new StringContent(expectedXml, Encoding.UTF8, acceptHeader)
|
||||||
|
};
|
||||||
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptHeader));
|
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(acceptHeader));
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -89,25 +77,80 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
XmlAssert.Equal(expectedXml, responseData);
|
XmlAssert.Equal(expectedXml, responseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ConditionalTheory]
|
public static TheoryData<string, string> InvalidInputAndHeadersData
|
||||||
// Mono issue - https://github.com/aspnet/External/issues/18
|
{
|
||||||
// XmlSerializer test is disabled Mono.Xml2.XmlTextReader.ReadText is unable to read the XML.
|
get
|
||||||
// This is fixed in mono 4.3.0.
|
{
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono)]
|
return new TheoryData<string, string>
|
||||||
[InlineData("application/xml-xmlser")]
|
{
|
||||||
[InlineData("application/xml-dcs")]
|
{
|
||||||
public async Task IsReturnedInExpectedFormat(string acceptHeader)
|
"application/xml-dcs",
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
|
"<Employee xmlns =\"http://schemas.datacontract.org/2004/07/XmlFormattersWebSite.Models\">" +
|
||||||
|
"<Id>2</Id><Name>foo</Name></Employee>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"application/xml-xmlser",
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
|
"<Employee>" +
|
||||||
|
"<Id>2</Id><Name>foo</Name></Employee>"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(InvalidInputAndHeadersData))]
|
||||||
|
public async Task IsReturnedInExpectedFormat(string acceptHeader, string inputXml)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
|
||||||
"<Employee xmlns=\"http://schemas.datacontract.org/2004/07/XmlFormattersWebSite.Models\">" +
|
|
||||||
"<Id>2</Id><Name>foo</Name></Employee>";
|
|
||||||
var expected = "<Error><Id>The field Id must be between 10 and 100.</Id>" +
|
var expected = "<Error><Id>The field Id must be between 10 and 100.</Id>" +
|
||||||
"<Name>The field Name must be a string or array type with a minimum " +
|
"<Name>The field Name must be a string or array type with a minimum " +
|
||||||
"length of '15'.</Name></Error>";
|
"length of '15'.</Name></Error>";
|
||||||
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/SerializableError/CreateEmployee");
|
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/SerializableError/CreateEmployee");
|
||||||
request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(acceptHeader));
|
request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(acceptHeader));
|
||||||
request.Content = new StringContent(input, Encoding.UTF8, "application/xml-dcs");
|
request.Content = new StringContent(inputXml, Encoding.UTF8, acceptHeader);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.SendAsync(request);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||||
|
var responseData = await response.Content.ReadAsStringAsync();
|
||||||
|
XmlAssert.Equal(expected, responseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TheoryData<string, string> IncorrectTopLevelInputAndHeadersData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new TheoryData<string, string>
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"application/xml-dcs",
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
|
"<Employees xmlns =\"http://schemas.datacontract.org/2004/07/XmlFormattersWebSite.Models\">" +
|
||||||
|
"<Id>2</Id><Name>foo</Name></Employee>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"application/xml-xmlser",
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||||
|
"<Employees>" +
|
||||||
|
"<Id>2</Id><Name>foo</Name></Employee>"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(IncorrectTopLevelInputAndHeadersData))]
|
||||||
|
public async Task IncorrectTopLevelElement_ReturnsExpectedError(string acceptHeader, string inputXml)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "<Error><MVC-Empty>An error occurred while deserializing input data.</MVC-Empty></Error>";
|
||||||
|
var request = new HttpRequestMessage(HttpMethod.Post, "http://localhost/SerializableError/CreateEmployee");
|
||||||
|
request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(acceptHeader));
|
||||||
|
request.Content = new StringContent(inputXml, Encoding.UTF8, acceptHeader);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var response = await Client.SendAsync(request);
|
var response = await Client.SendAsync(request);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue