[Fixes #852] XmlDictionaryReader.CreateTextReader overload which supports Encoding is missing
This commit is contained in:
parent
ac908d405e
commit
9a6f8b392d
|
|
@ -6,6 +6,7 @@ using System.Collections.Concurrent;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using Microsoft.AspNet.Mvc.Internal;
|
||||
|
|
@ -95,7 +96,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
{
|
||||
var request = context.ActionContext.HttpContext.Request;
|
||||
|
||||
using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body)))
|
||||
MediaTypeHeaderValue requestContentType;
|
||||
MediaTypeHeaderValue.TryParse(request.ContentType , out requestContentType);
|
||||
var effectiveEncoding = SelectCharacterEncoding(requestContentType);
|
||||
|
||||
using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), effectiveEncoding))
|
||||
{
|
||||
var type = GetSerializableType(context.ModelType);
|
||||
|
||||
|
|
@ -131,11 +136,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
/// Called during deserialization to get the <see cref="XmlReader"/>.
|
||||
/// </summary>
|
||||
/// <param name="readStream">The <see cref="Stream"/> from which to read.</param>
|
||||
/// <param name="encoding">The <see cref="Encoding"/> used to read the stream.</param>
|
||||
/// <returns>The <see cref="XmlReader"/> used during deserialization.</returns>
|
||||
protected virtual XmlReader CreateXmlReader([NotNull] Stream readStream)
|
||||
protected virtual XmlReader CreateXmlReader([NotNull] Stream readStream, [NotNull] Encoding encoding)
|
||||
{
|
||||
return XmlDictionaryReader.CreateTextReader(
|
||||
readStream, _readerQuotas);
|
||||
return XmlDictionaryReader.CreateTextReader(readStream, encoding, _readerQuotas, onClose: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
|
|
@ -71,7 +72,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
{
|
||||
var request = context.ActionContext.HttpContext.Request;
|
||||
|
||||
using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body)))
|
||||
MediaTypeHeaderValue requestContentType;
|
||||
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
|
||||
var effectiveEncoding = SelectCharacterEncoding(requestContentType);
|
||||
|
||||
using (var xmlReader = CreateXmlReader(new NonDisposableStream(request.Body), effectiveEncoding))
|
||||
{
|
||||
var type = GetSerializableType(context.ModelType);
|
||||
|
||||
|
|
@ -116,11 +121,11 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
/// Called during deserialization to get the <see cref="XmlReader"/>.
|
||||
/// </summary>
|
||||
/// <param name="readStream">The <see cref="Stream"/> from which to read.</param>
|
||||
/// <param name="encoding">The <see cref="Encoding"/> used to read the stream.</param>
|
||||
/// <returns>The <see cref="XmlReader"/> used during deserialization.</returns>
|
||||
protected virtual XmlReader CreateXmlReader([NotNull] Stream readStream)
|
||||
protected virtual XmlReader CreateXmlReader([NotNull] Stream readStream, [NotNull] Encoding encoding)
|
||||
{
|
||||
return XmlDictionaryReader.CreateTextReader(
|
||||
readStream, _readerQuotas);
|
||||
return XmlDictionaryReader.CreateTextReader(readStream, encoding, _readerQuotas, onClose: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -289,15 +289,15 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_ThrowsOnInvalidCharacters()
|
||||
public async Task ReadAsync_FallsbackToUTF8_WhenCharSet_NotInContentType()
|
||||
{
|
||||
// Arrange
|
||||
var expectedException = TestPlatformHelper.IsMono ? typeof(SerializationException) :
|
||||
typeof(XmlException);
|
||||
var expectedMessage = TestPlatformHelper.IsMono ?
|
||||
"Expected element 'TestLevelTwo' in namespace '', but found Element node 'DummyClass' in namespace ''" :
|
||||
"The encoding in the declaration 'UTF-8' does not match the encoding of the document 'utf-16LE'.";
|
||||
var inpStart = Encodings.UTF16EncodingLittleEndian.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||
"The expected encoding 'utf-8' does not match the actual encoding 'utf-16LE'.";
|
||||
var inpStart = Encodings.UTF16EncodingLittleEndian.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-16\"?>" +
|
||||
"<DummyClass><SampleInt>");
|
||||
byte[] inp = { 192, 193 };
|
||||
var inpEnd = Encodings.UTF16EncodingLittleEndian.GetBytes("</SampleInt></DummyClass>");
|
||||
|
|
@ -315,6 +315,27 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_UsesContentTypeCharSet_ToReadStream()
|
||||
{
|
||||
// Arrange
|
||||
var expectedException = TestPlatformHelper.IsMono ? typeof(SerializationException) :
|
||||
typeof(XmlException);
|
||||
var expectedMessage = TestPlatformHelper.IsMono ?
|
||||
"Expected element 'TestLevelTwo' in namespace '', but found Element node 'DummyClass' in namespace ''" :
|
||||
"The expected encoding 'utf-16LE' does not match the actual encoding 'utf-8'.";
|
||||
var inputBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||
"<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));
|
||||
|
||||
// Act
|
||||
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
|
||||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_IgnoresBOMCharacters()
|
||||
{
|
||||
|
|
@ -359,8 +380,10 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
|
||||
var formatter = new XmlDataContractSerializerInputFormatter();
|
||||
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
|
||||
var context = GetInputFormatterContext(contentBytes, typeof(TestLevelOne));
|
||||
|
||||
var actionContext = GetActionContext(contentBytes, contentType: "application/xml; charset=utf-16");
|
||||
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
|
||||
|
||||
// Act
|
||||
var model = await formatter.ReadAsync(context);
|
||||
|
||||
|
|
|
|||
|
|
@ -296,16 +296,16 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_ThrowsOnInvalidCharacters()
|
||||
public async Task ReadAsync_FallsbackToUTF8_WhenCharSet_NotInContentType()
|
||||
{
|
||||
// Arrange
|
||||
var expectedException = TestPlatformHelper.IsMono ? typeof(InvalidOperationException) :
|
||||
typeof(XmlException);
|
||||
var expectedMessage = TestPlatformHelper.IsMono ?
|
||||
"There is an error in XML document." :
|
||||
"The encoding in the declaration 'UTF-8' does not match the encoding of the document 'utf-16LE'.";
|
||||
"The expected encoding 'utf-8' does not match the actual encoding 'utf-16LE'.";
|
||||
|
||||
var inpStart = Encodings.UTF16EncodingLittleEndian.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||
var inpStart = Encodings.UTF16EncodingLittleEndian.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-16\"?>" +
|
||||
"<DummyClass><SampleInt>");
|
||||
byte[] inp = { 192, 193 };
|
||||
var inpEnd = Encodings.UTF16EncodingLittleEndian.GetBytes("</SampleInt></DummyClass>");
|
||||
|
|
@ -323,6 +323,28 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_UsesContentTypeCharSet_ToReadStream()
|
||||
{
|
||||
// Arrange
|
||||
var expectedException = TestPlatformHelper.IsMono ? typeof(InvalidOperationException) :
|
||||
typeof(XmlException);
|
||||
var expectedMessage = TestPlatformHelper.IsMono ?
|
||||
"There is an error in XML document." :
|
||||
"The expected encoding 'utf-16LE' does not match the actual encoding 'utf-8'.";
|
||||
|
||||
var inputBytes = Encodings.UTF8EncodingWithoutBOM.GetBytes("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
|
||||
"<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));
|
||||
|
||||
// Act and Assert
|
||||
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
|
||||
Assert.Equal(expectedMessage, ex.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadAsync_IgnoresBOMCharacters()
|
||||
{
|
||||
|
|
@ -369,7 +391,9 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
|
||||
var formatter = new XmlSerializerInputFormatter();
|
||||
var contentBytes = Encodings.UTF16EncodingLittleEndian.GetBytes(input);
|
||||
var context = GetInputFormatterContext(contentBytes, typeof(TestLevelOne));
|
||||
|
||||
var actionContext = GetActionContext(contentBytes, contentType: "application/xml; charset=utf-16");
|
||||
var context = new InputFormatterContext(actionContext, typeof(TestLevelOne));
|
||||
|
||||
// Act
|
||||
var model = await formatter.ReadAsync(context);
|
||||
|
|
@ -398,6 +422,7 @@ namespace Microsoft.AspNet.Mvc.Xml
|
|||
new AspNet.Routing.RouteData(),
|
||||
new ActionDescriptor());
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(byte[] contentBytes,
|
||||
string contentType = "application/xml")
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue