[Fixes #1841] Change XML DCS and XmlSerializer output formatters to not derive from the base XmlOutputFormatter

This commit is contained in:
Kiran Challa 2015-01-19 10:14:10 -08:00 committed by Kiran Challa
parent d51dad9560
commit 0e9091f0eb
8 changed files with 202 additions and 110 deletions

View File

@ -34,5 +34,19 @@ namespace Microsoft.AspNet.Mvc
MaxStringContentLength = int.MaxValue
};
}
/// <summary>
/// Gets the default XmlWriterSettings.
/// </summary>
/// <returns>Default <see cref="XmlWriterSettings"/></returns>
public static XmlWriterSettings GetDefaultXmlWriterSettings()
{
return new XmlWriterSettings
{
OmitXmlDeclaration = true,
CloseOutput = false,
CheckCharacters = false
};
}
}
}

View File

@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
@ -12,14 +14,14 @@ namespace Microsoft.AspNet.Mvc
/// This class handles serialization of objects
/// to XML using <see cref="DataContractSerializer"/>
/// </summary>
public class XmlDataContractSerializerOutputFormatter : XmlOutputFormatter
public class XmlDataContractSerializerOutputFormatter : OutputFormatter
{
/// <summary>
/// Initializes a new instance of <see cref="XmlDataContractSerializerOutputFormatter"/>
/// with default XmlWriterSettings
/// </summary>
public XmlDataContractSerializerOutputFormatter()
: this(GetDefaultXmlWriterSettings())
public XmlDataContractSerializerOutputFormatter() :
this(FormattingUtilities.GetDefaultXmlWriterSettings())
{
}
@ -28,8 +30,39 @@ namespace Microsoft.AspNet.Mvc
/// </summary>
/// <param name="writerSettings">The settings to be used by the <see cref="DataContractSerializer"/>.</param>
public XmlDataContractSerializerOutputFormatter([NotNull] XmlWriterSettings writerSettings)
: base(writerSettings)
{
SupportedEncodings.Add(Encodings.UTF8EncodingWithoutBOM);
SupportedEncodings.Add(Encodings.UTF16EncodingLittleEndian);
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xml"));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/xml"));
WriterSettings = writerSettings;
}
/// <summary>
/// Gets the settings to be used by the XmlWriter.
/// </summary>
public XmlWriterSettings WriterSettings { get; }
/// <summary>
/// Gets the type of the object to be serialized.
/// </summary>
/// <param name="declaredType">The declared type.</param>
/// <param name="runtimeType">The runtime type.</param>
/// <returns>The type of the object to be serialized.</returns>
protected virtual Type GetSerializableType(Type declaredType, Type runtimeType)
{
if (declaredType == null ||
declaredType == typeof(object))
{
if (runtimeType != null)
{
return runtimeType;
}
}
return declaredType;
}
/// <inheritdoc />
@ -62,6 +95,17 @@ namespace Microsoft.AspNet.Mvc
}
}
/// <summary>
/// Creates a new instance of <see cref="XmlWriter"/> using the given stream and the <see cref="WriterSettings"/>.
/// </summary>
/// <param name="writeStream">The stream on which the XmlWriter should operate on.</param>
/// <returns>A new instance of <see cref="XmlWriter"/></returns>
public virtual XmlWriter CreateXmlWriter([NotNull] Stream writeStream,
[NotNull] XmlWriterSettings xmlWriterSettings)
{
return XmlWriter.Create(writeStream, xmlWriterSettings);
}
/// <inheritdoc />
public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
{

View File

@ -1,77 +0,0 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Xml;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
/// <summary>
/// Abstract base class from which all XML Output Formatters derive from.
/// </summary>
public abstract class XmlOutputFormatter : OutputFormatter
{
public XmlOutputFormatter([NotNull] XmlWriterSettings xmlWriterSettings)
{
SupportedEncodings.Add(Encodings.UTF8EncodingWithoutBOM);
SupportedEncodings.Add(Encodings.UTF16EncodingLittleEndian);
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xml"));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/xml"));
WriterSettings = xmlWriterSettings;
}
/// <summary>
/// Gets or sets the settings to be used by the XmlWriter.
/// </summary>
public XmlWriterSettings WriterSettings { get; private set; }
/// <summary>
/// Gets the type of the object to be serialized.
/// </summary>
/// <param name="declaredType">The declared type.</param>
/// <param name="runtimeType">The runtime type.</param>
/// <returns>The type of the object to be serialized.</returns>
protected virtual Type GetSerializableType(Type declaredType, Type runtimeType)
{
if (declaredType == null ||
declaredType == typeof(object))
{
if (runtimeType != null)
{
return runtimeType;
}
}
return declaredType;
}
/// <summary>
/// Gets the default XmlWriterSettings.
/// </summary>
/// <returns>Default <see cref="XmlWriterSettings"/></returns>
public static XmlWriterSettings GetDefaultXmlWriterSettings()
{
return new XmlWriterSettings
{
OmitXmlDeclaration = true,
CloseOutput = false,
CheckCharacters = false
};
}
/// <summary>
/// Creates a new instance of <see cref="XmlWriter"/> using the given stream and the WriterSettings.
/// </summary>
/// <param name="writeStream">The stream on which the XmlWriter should operate on.</param>
/// <returns>A new instance of <see cref="XmlWriter"/></returns>
public virtual XmlWriter CreateXmlWriter([NotNull] Stream writeStream,
[NotNull] XmlWriterSettings xmlWriterSettings)
{
return XmlWriter.Create(writeStream, xmlWriterSettings);
}
}
}

View File

@ -2,9 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.Net.Http.Headers;
namespace Microsoft.AspNet.Mvc
{
@ -12,14 +14,14 @@ namespace Microsoft.AspNet.Mvc
/// This class handles serialization of objects
/// to XML using <see cref="XmlSerializer"/>
/// </summary>
public class XmlSerializerOutputFormatter : XmlOutputFormatter
public class XmlSerializerOutputFormatter : OutputFormatter
{
/// <summary>
/// Initializes a new instance of <see cref="XmlSerializerOutputFormatter"/>
/// with default XmlWriterSettings.
/// </summary>
public XmlSerializerOutputFormatter()
: this(GetDefaultXmlWriterSettings())
public XmlSerializerOutputFormatter() :
this(FormattingUtilities.GetDefaultXmlWriterSettings())
{
}
@ -28,8 +30,39 @@ namespace Microsoft.AspNet.Mvc
/// </summary>
/// <param name="writerSettings">The settings to be used by the <see cref="XmlSerializer"/>.</param>
public XmlSerializerOutputFormatter([NotNull] XmlWriterSettings writerSettings)
: base(writerSettings)
{
SupportedEncodings.Add(Encodings.UTF8EncodingWithoutBOM);
SupportedEncodings.Add(Encodings.UTF16EncodingLittleEndian);
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("application/xml"));
SupportedMediaTypes.Add(MediaTypeHeaderValue.Parse("text/xml"));
WriterSettings = writerSettings;
}
/// <summary>
/// Gets the settings to be used by the XmlWriter.
/// </summary>
public XmlWriterSettings WriterSettings { get; }
/// <summary>
/// Gets the type of the object to be serialized.
/// </summary>
/// <param name="declaredType">The declared type.</param>
/// <param name="runtimeType">The runtime type.</param>
/// <returns>The type of the object to be serialized.</returns>
protected virtual Type GetSerializableType(Type declaredType, Type runtimeType)
{
if (declaredType == null ||
declaredType == typeof(object))
{
if (runtimeType != null)
{
return runtimeType;
}
}
return declaredType;
}
/// <inheritdoc />
@ -58,6 +91,17 @@ namespace Microsoft.AspNet.Mvc
}
}
/// <summary>
/// Creates a new instance of <see cref="XmlWriter"/> using the given stream and the <see cref="WriterSettings"/>.
/// </summary>
/// <param name="writeStream">The stream on which the XmlWriter should operate on.</param>
/// <returns>A new instance of <see cref="XmlWriter"/></returns>
public virtual XmlWriter CreateXmlWriter([NotNull] Stream writeStream,
[NotNull] XmlWriterSettings xmlWriterSettings)
{
return XmlWriter.Create(writeStream, xmlWriterSettings);
}
/// <inheritdoc />
public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
{

View File

@ -13,8 +13,7 @@ namespace Microsoft.AspNet.Mvc
/// <param name="options">The MvcOptions</param>
public static void AddXmlDataContractSerializerFormatter([NotNull] this MvcOptions options)
{
options.OutputFormatters.Add(
new XmlDataContractSerializerOutputFormatter(XmlOutputFormatter.GetDefaultXmlWriterSettings()));
options.OutputFormatters.Add(new XmlDataContractSerializerOutputFormatter());
options.InputFormatters.Add(new XmlDataContractSerializerInputFormatter());
}

View File

@ -492,7 +492,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
new HttpNoContentOutputFormatter(),
new StringOutputFormatter(),
new JsonOutputFormatter(),
new XmlDataContractSerializerOutputFormatter(XmlSerializerOutputFormatter.GetDefaultXmlWriterSettings())
new XmlDataContractSerializerOutputFormatter()
};
var response = GetMockHttpResponse();
@ -533,7 +533,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
new HttpNoContentOutputFormatter(),
new StringOutputFormatter(),
new JsonOutputFormatter(),
new XmlDataContractSerializerOutputFormatter(XmlSerializerOutputFormatter.GetDefaultXmlWriterSettings())
new XmlDataContractSerializerOutputFormatter()
};
var response = GetMockHttpResponse();
@ -568,7 +568,7 @@ namespace Microsoft.AspNet.Mvc.Core.Test.ActionResults
new HttpNoContentOutputFormatter(),
new StringOutputFormatter(),
new JsonOutputFormatter(),
new XmlDataContractSerializerOutputFormatter(XmlSerializerOutputFormatter.GetDefaultXmlWriterSettings())
new XmlDataContractSerializerOutputFormatter()
};
var response = GetMockHttpResponse();

View File

@ -84,13 +84,51 @@ namespace Microsoft.AspNet.Mvc.Core
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
}
[Fact]
public void DefaultConstructor_ExpectedWriterSettings_Created()
{
// Arrange and Act
var formatter = new XmlDataContractSerializerOutputFormatter();
// Assert
var writerSettings = formatter.WriterSettings;
Assert.NotNull(writerSettings);
Assert.True(writerSettings.OmitXmlDeclaration);
Assert.False(writerSettings.CloseOutput);
Assert.False(writerSettings.CheckCharacters);
}
[Fact]
public async Task SuppliedWriterSettings_TakeAffect()
{
// Arrange
var writerSettings = FormattingUtilities.GetDefaultXmlWriterSettings();
writerSettings.OmitXmlDeclaration = false;
var sampleInput = new DummyClass { SampleInt = 10 };
var formatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
var formatter = new XmlDataContractSerializerOutputFormatter(writerSettings);
var expectedOutput = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
"<SampleInt>10</SampleInt></DummyClass>";
// Act
await formatter.WriteAsync(formatterContext);
// Assert
Assert.Same(writerSettings, formatter.WriterSettings);
var responseStream = formatterContext.ActionContext.HttpContext.Response.Body;
Assert.NotNull(responseStream);
responseStream.Position = 0;
var actualOutput = new StreamReader(responseStream, Encoding.UTF8).ReadToEnd();
Assert.Equal(expectedOutput, actualOutput);
}
[Fact]
public async Task XmlDataContractSerializerOutputFormatterWritesSimpleTypes()
{
// Arrange
var sampleInput = new DummyClass { SampleInt = 10 };
var formatter = new XmlDataContractSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlDataContractSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
// Act
@ -118,8 +156,7 @@ namespace Microsoft.AspNet.Mvc.Core
sampleString = "TestLevelOne string"
}
};
var formatter = new XmlDataContractSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlDataContractSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
// Act
@ -168,8 +205,7 @@ namespace Microsoft.AspNet.Mvc.Core
var sampleInput = new DummyClass { SampleInt = 10 };
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType(),
"application/xml; charset=utf-16");
var formatter = new XmlDataContractSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlDataContractSerializerOutputFormatter();
formatter.WriterSettings.OmitXmlDeclaration = false;
// Act
@ -190,8 +226,7 @@ namespace Microsoft.AspNet.Mvc.Core
{
// Arrange
var sampleInput = new DummyClass { SampleInt = 10 };
var formatter = new XmlDataContractSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlDataContractSerializerOutputFormatter();
formatter.WriterSettings.Indent = true;
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
@ -213,8 +248,7 @@ namespace Microsoft.AspNet.Mvc.Core
{
// Arrange
var sampleInput = new DummyClass { SampleInt = 10 };
var formatter = new XmlDataContractSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlDataContractSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
// Act

View File

@ -66,13 +66,51 @@ namespace Microsoft.AspNet.Mvc.Core
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
}
[Fact]
public void DefaultConstructor_ExpectedWriterSettings_Created()
{
// Arrange and Act
var formatter = new XmlSerializerOutputFormatter();
// Assert
var writerSettings = formatter.WriterSettings;
Assert.NotNull(writerSettings);
Assert.True(writerSettings.OmitXmlDeclaration);
Assert.False(writerSettings.CloseOutput);
Assert.False(writerSettings.CheckCharacters);
}
[Fact]
public async Task SuppliedWriterSettings_TakeAffect()
{
// Arrange
var writerSettings = FormattingUtilities.GetDefaultXmlWriterSettings();
writerSettings.OmitXmlDeclaration = false;
var sampleInput = new DummyClass { SampleInt = 10 };
var formatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
var formatter = new XmlSerializerOutputFormatter(writerSettings);
var expectedOutput = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>";
// Act
await formatter.WriteAsync(formatterContext);
// Assert
Assert.Same(writerSettings, formatter.WriterSettings);
var responseStream = formatterContext.ActionContext.HttpContext.Response.Body;
Assert.NotNull(responseStream);
responseStream.Position = 0;
var actualOutput = new StreamReader(responseStream, Encoding.UTF8).ReadToEnd();
Assert.Equal(expectedOutput, actualOutput);
}
[Fact]
public async Task XmlSerializerOutputFormatterWritesSimpleTypes()
{
// Arrange
var sampleInput = new DummyClass { SampleInt = 10 };
var formatter = new XmlSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
// Act
@ -101,8 +139,7 @@ namespace Microsoft.AspNet.Mvc.Core
sampleString = "TestLevelOne string"
}
};
var formatter = new XmlSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
// Act
@ -152,8 +189,7 @@ namespace Microsoft.AspNet.Mvc.Core
var sampleInput = new DummyClass { SampleInt = 10 };
var outputFormatterContext =
GetOutputFormatterContext(sampleInput, sampleInput.GetType(), "application/xml; charset=utf-16");
var formatter = new XmlSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlSerializerOutputFormatter();
formatter.WriterSettings.OmitXmlDeclaration = false;
// Act
@ -174,8 +210,7 @@ namespace Microsoft.AspNet.Mvc.Core
{
// Arrange
var sampleInput = new DummyClass { SampleInt = 10 };
var formatter = new XmlSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlSerializerOutputFormatter();
formatter.WriterSettings.Indent = true;
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
@ -197,8 +232,7 @@ namespace Microsoft.AspNet.Mvc.Core
{
// Arrange
var sampleInput = new DummyClass { SampleInt = 10 };
var formatter = new XmlSerializerOutputFormatter(
XmlOutputFormatter.GetDefaultXmlWriterSettings());
var formatter = new XmlSerializerOutputFormatter();
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
// Act