Changes to enable XML Output Formatters.
- Unit / Functional tests for the same.
This commit is contained in:
parent
1a4bd25e0f
commit
2920c55116
4
Mvc.sln
4
Mvc.sln
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 14.0.21902.1
|
VisualStudioVersion = 14.0.22013.1
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -67,7 +67,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
global.json = global.json
|
global.json = global.json
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ConnegWebsite", "test\WebSites\ConnegWebSite\ConnegWebsite.kproj", "{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ConnegWebsite", "test\WebSites\ConnegWebSite\ConnegWebsite.kproj", "{C6E5AFFA-890A-448F-8DE3-878B1D3C9FC7}"
|
||||||
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AntiForgeryWebSite", "test\WebSites\AntiForgeryWebSite\AntiForgeryWebSite.kproj", "{A353B17E-A940-4CE8-8BF9-179E24A9041F}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "AntiForgeryWebSite", "test\WebSites\AntiForgeryWebSite\AntiForgeryWebSite.kproj", "{A353B17E-A940-4CE8-8BF9-179E24A9041F}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// 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.Runtime.Serialization;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class handles serialization of objects
|
||||||
|
/// to XML using <see cref="DataContractSerializer"/>
|
||||||
|
/// </summary>
|
||||||
|
public class XmlDataContractSerializerOutputFormatter : XmlOutputFormatter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref="XmlDataContractSerializerOutputFormatter"/>
|
||||||
|
/// with default XmlWriterSettings
|
||||||
|
/// </summary>
|
||||||
|
public XmlDataContractSerializerOutputFormatter()
|
||||||
|
:this(GetDefaultXmlWriterSettings())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref="XmlDataContractSerializerOutputFormatter"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writerSettings">The settings to be used by the <see cref="DataContractSerializer"/>.</param>
|
||||||
|
public XmlDataContractSerializerOutputFormatter([NotNull] XmlWriterSettings writerSettings)
|
||||||
|
:base(writerSettings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new instance of <see cref="DataContractSerializer"/> for the given object type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type of object for which the serializer should be created.</param>
|
||||||
|
/// <returns>A new instance of <see cref="DataContractSerializer"/></returns>
|
||||||
|
public virtual DataContractSerializer CreateDataContractSerializer([NotNull] Type type)
|
||||||
|
{
|
||||||
|
return new DataContractSerializer(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
|
||||||
|
{
|
||||||
|
var response = context.ActionContext.HttpContext.Response;
|
||||||
|
|
||||||
|
var tempWriterSettings = WriterSettings.Clone();
|
||||||
|
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||||
|
using (var xmlWriter = CreateXmlWriter(response.Body, tempWriterSettings))
|
||||||
|
{
|
||||||
|
var dataContractSerializer = CreateDataContractSerializer(context.DeclaredType);
|
||||||
|
dataContractSerializer.WriteObject(xmlWriter, context.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
// 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.IO;
|
||||||
|
using System.Xml;
|
||||||
|
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||||
|
|
||||||
|
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 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
// 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.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class handles serialization of objects
|
||||||
|
/// to XML using <see cref="XmlSerializer"/>
|
||||||
|
/// </summary>
|
||||||
|
public class XmlSerializerOutputFormatter : XmlOutputFormatter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref="XmlSerializerOutputFormatter"/>
|
||||||
|
/// with default XmlWriterSettings.
|
||||||
|
/// </summary>
|
||||||
|
public XmlSerializerOutputFormatter()
|
||||||
|
:this(GetDefaultXmlWriterSettings())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of <see cref="XmlSerializerOutputFormatter"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writerSettings">The settings to be used by the <see cref="XmlSerializer"/>.</param>
|
||||||
|
public XmlSerializerOutputFormatter([NotNull] XmlWriterSettings writerSettings)
|
||||||
|
:base(writerSettings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new instance of <see cref="XmlSerializer"/> for the given object type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type of object for which the serializer should be created.</param>
|
||||||
|
/// <returns>A new instance of <see cref="XmlSerializer"/></returns>
|
||||||
|
public virtual XmlSerializer CreateXmlSerializer([NotNull] Type type)
|
||||||
|
{
|
||||||
|
return new XmlSerializer(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override Task WriteResponseBodyAsync([NotNull] OutputFormatterContext context)
|
||||||
|
{
|
||||||
|
var response = context.ActionContext.HttpContext.Response;
|
||||||
|
|
||||||
|
var tempWriterSettings = WriterSettings.Clone();
|
||||||
|
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||||
|
using (var xmlWriter = CreateXmlWriter(response.Body, tempWriterSettings))
|
||||||
|
{
|
||||||
|
var xmlSerializer = CreateXmlSerializer(context.DeclaredType);
|
||||||
|
xmlSerializer.Serialize(xmlWriter, context.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -38,6 +38,10 @@ namespace Microsoft.AspNet.Mvc
|
||||||
options.OutputFormatters.Add(new TextPlainFormatter());
|
options.OutputFormatters.Add(new TextPlainFormatter());
|
||||||
options.OutputFormatters.Add(new JsonOutputFormatter(JsonOutputFormatter.CreateDefaultSettings(),
|
options.OutputFormatters.Add(new JsonOutputFormatter(JsonOutputFormatter.CreateDefaultSettings(),
|
||||||
indent: false));
|
indent: false));
|
||||||
|
options.OutputFormatters.Add(
|
||||||
|
new XmlDataContractSerializerOutputFormatter(XmlOutputFormatter.GetDefaultXmlWriterSettings()));
|
||||||
|
options.OutputFormatters.Add(
|
||||||
|
new XmlSerializerOutputFormatter(XmlOutputFormatter.GetDefaultXmlWriterSettings()));
|
||||||
|
|
||||||
// Set up ValueProviders
|
// Set up ValueProviders
|
||||||
options.ValueProviderFactories.Add(new RouteValueValueProviderFactory());
|
options.ValueProviderFactories.Add(new RouteValueValueProviderFactory());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
// 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.Runtime.Serialization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Core
|
||||||
|
{
|
||||||
|
public class XmlDataContractSerializerOutputFormatterTests
|
||||||
|
{
|
||||||
|
[DataContract(Name = "DummyClass", Namespace = "")]
|
||||||
|
public class DummyClass
|
||||||
|
{
|
||||||
|
[DataMember]
|
||||||
|
public int SampleInt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataContract(Name = "TestLevelOne", Namespace = "")]
|
||||||
|
public class TestLevelOne
|
||||||
|
{
|
||||||
|
[DataMember]
|
||||||
|
public int SampleInt { get; set; }
|
||||||
|
[DataMember]
|
||||||
|
public string sampleString;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DataContract(Name = "TestLevelTwo", Namespace = "")]
|
||||||
|
public class TestLevelTwo
|
||||||
|
{
|
||||||
|
[DataMember]
|
||||||
|
public string SampleString { get; set; }
|
||||||
|
[DataMember]
|
||||||
|
public TestLevelOne TestOne { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlDataContractSerializerOutputFormatterWritesSimpleTypes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
||||||
|
.ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlDataContractSerializerOutputFormatterWritesComplexTypes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new TestLevelTwo
|
||||||
|
{
|
||||||
|
SampleString = "TestString",
|
||||||
|
TestOne = new TestLevelOne
|
||||||
|
{
|
||||||
|
SampleInt = 10,
|
||||||
|
sampleString = "TestLevelOne string"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<TestLevelTwo xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleString>TestString</SampleString>" +
|
||||||
|
"<TestOne><SampleInt>10</SampleInt><sampleString>TestLevelOne string</sampleString>" +
|
||||||
|
"</TestOne></TestLevelTwo>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
||||||
|
.ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlDataContractSerializerOutputFormatterWritesOnModifiedWriterSettings()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||||
|
new System.Xml.XmlWriterSettings
|
||||||
|
{
|
||||||
|
OmitXmlDeclaration = false,
|
||||||
|
CloseOutput = false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
|
||||||
|
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8).ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlDataContractSerializerOutputFormatterWritesUTF16Output()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType(),
|
||||||
|
"application/xml; charset=utf-16");
|
||||||
|
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
formatter.WriterSettings.OmitXmlDeclaration = false;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
|
||||||
|
"<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"<SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
||||||
|
Encodings.UTF16EncodingLittleEndian).ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlDataContractSerializerOutputFormatterWritesIndentedOutput()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
formatter.WriterSettings.Indent = true;
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
var outputString = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
||||||
|
Encoding.UTF8).ReadToEnd();
|
||||||
|
Assert.Equal("<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">" +
|
||||||
|
"\r\n <SampleInt>10</SampleInt>\r\n</DummyClass>",
|
||||||
|
outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task VerifyBodyIsNotClosedAfterOutputIsWritten()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
|
||||||
|
string contentType = "application/xml; charset=utf-8")
|
||||||
|
{
|
||||||
|
return new OutputFormatterContext
|
||||||
|
{
|
||||||
|
Object = outputValue,
|
||||||
|
DeclaredType = outputType,
|
||||||
|
ActionContext = GetActionContext(contentType)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionContext GetActionContext(string contentType)
|
||||||
|
{
|
||||||
|
var request = new Mock<HttpRequest>();
|
||||||
|
var headers = new Mock<IHeaderDictionary>();
|
||||||
|
request.Setup(r => r.ContentType).Returns(contentType);
|
||||||
|
request.SetupGet(r => r.Headers).Returns(headers.Object);
|
||||||
|
request.SetupGet(f => f.AcceptCharset).Returns(contentType.Split('=')[1]);
|
||||||
|
var response = new Mock<HttpResponse>();
|
||||||
|
response.SetupGet(f => f.Body).Returns(new MemoryStream());
|
||||||
|
var httpContext = new Mock<HttpContext>();
|
||||||
|
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
||||||
|
httpContext.SetupGet(c => c.Response).Returns(response.Object);
|
||||||
|
return new ActionContext(httpContext.Object, routeData: null, actionDescriptor: null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,202 @@
|
||||||
|
// 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.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.Core
|
||||||
|
{
|
||||||
|
public class XmlSerializerOutputFormatterTests
|
||||||
|
{
|
||||||
|
public class DummyClass
|
||||||
|
{
|
||||||
|
public int SampleInt { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestLevelOne
|
||||||
|
{
|
||||||
|
public int SampleInt { get; set; }
|
||||||
|
public string sampleString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TestLevelTwo
|
||||||
|
{
|
||||||
|
public string SampleString { get; set; }
|
||||||
|
public TestLevelOne TestOne { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlSerializerOutputFormatterWritesSimpleTypes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var formatter = new XmlSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
||||||
|
.ReadToEnd());
|
||||||
|
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlSerializerOutputFormatterWritesComplexTypes()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new TestLevelTwo
|
||||||
|
{
|
||||||
|
SampleString = "TestString",
|
||||||
|
TestOne = new TestLevelOne
|
||||||
|
{
|
||||||
|
SampleInt = 10,
|
||||||
|
sampleString = "TestLevelOne string"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var formatter = new XmlSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<TestLevelTwo xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleString>TestString</SampleString>" +
|
||||||
|
"<TestOne><sampleString>TestLevelOne string</sampleString>" +
|
||||||
|
"<SampleInt>10</SampleInt></TestOne></TestLevelTwo>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
||||||
|
.ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlSerializerOutputFormatterWritesOnModifiedWriterSettings()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
var formatter = new XmlSerializerOutputFormatter(
|
||||||
|
new System.Xml.XmlWriterSettings
|
||||||
|
{
|
||||||
|
OmitXmlDeclaration = false,
|
||||||
|
CloseOutput = false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<?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>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body, Encoding.UTF8)
|
||||||
|
.ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlSerializerOutputFormatterWritesUTF16Output()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var outputFormatterContext =
|
||||||
|
GetOutputFormatterContext(sampleInput, sampleInput.GetType(), "application/xml; charset=utf-16");
|
||||||
|
var formatter = new XmlSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
formatter.WriterSettings.OmitXmlDeclaration = false;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
Assert.Equal("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
|
||||||
|
"<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
||||||
|
Encodings.UTF16EncodingLittleEndian).ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlSerializerOutputFormatterWritesIndentedOutput()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var formatter = new XmlSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
formatter.WriterSettings.Indent = true;
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
outputFormatterContext.ActionContext.HttpContext.Response.Body.Position = 0;
|
||||||
|
var outputString = new StreamReader(outputFormatterContext.ActionContext.HttpContext.Response.Body,
|
||||||
|
Encoding.UTF8).ReadToEnd();
|
||||||
|
Assert.Equal("<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\r\n <SampleInt>10</SampleInt>\r\n</DummyClass>",
|
||||||
|
outputString);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task VerifyBodyIsNotClosedAfterOutputIsWritten()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var sampleInput = new DummyClass { SampleInt = 10 };
|
||||||
|
var formatter = new XmlSerializerOutputFormatter(
|
||||||
|
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||||
|
var outputFormatterContext = GetOutputFormatterContext(sampleInput, sampleInput.GetType());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await formatter.WriteAsync(outputFormatterContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(outputFormatterContext.ActionContext.HttpContext.Response.Body);
|
||||||
|
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
|
||||||
|
string contentType = "application/xml; charset=utf-8")
|
||||||
|
{
|
||||||
|
return new OutputFormatterContext
|
||||||
|
{
|
||||||
|
Object = outputValue,
|
||||||
|
DeclaredType = outputType,
|
||||||
|
ActionContext = GetActionContext(contentType)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionContext GetActionContext(string contentType)
|
||||||
|
{
|
||||||
|
var request = new Mock<HttpRequest>();
|
||||||
|
var headers = new Mock<IHeaderDictionary>();
|
||||||
|
request.Setup(r => r.ContentType).Returns(contentType);
|
||||||
|
request.SetupGet(r => r.Headers).Returns(headers.Object);
|
||||||
|
request.SetupGet(f => f.AcceptCharset).Returns(contentType.Split('=')[1]);
|
||||||
|
var response = new Mock<HttpResponse>();
|
||||||
|
response.SetupGet(f => f.Body).Returns(new MemoryStream());
|
||||||
|
var httpContext = new Mock<HttpContext>();
|
||||||
|
httpContext.SetupGet(c => c.Request).Returns(request.Object);
|
||||||
|
httpContext.SetupGet(c => c.Response).Returns(response.Object);
|
||||||
|
return new ActionContext(httpContext.Object, routeData: null, actionDescriptor: null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
// 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.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.TestHost;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
|
{
|
||||||
|
public class XmlOutputFormatterTests
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly Action<IBuilder> _app = new FormatterWebSite.Startup().Configure;
|
||||||
|
|
||||||
|
public XmlOutputFormatterTests()
|
||||||
|
{
|
||||||
|
_services = TestHelper.CreateServices("FormatterWebSite");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlDataContractSerializerOutputFormatterIsCalled()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_services, _app);
|
||||||
|
var client = server.Handler;
|
||||||
|
var headers = new Dictionary<string, string[]>();
|
||||||
|
headers.Add("Accept", new string[] { "application/xml;charset=utf-8" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.SendAsync("POST",
|
||||||
|
"http://localhost/Home/GetDummyClass?sampleInput=10", headers, null, null);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(200, response.StatusCode);
|
||||||
|
Assert.Equal("<DummyClass xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns=\"http://schemas.datacontract.org/2004/07/FormatterWebSite\">" +
|
||||||
|
"<SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
new StreamReader(response.Body, Encoding.UTF8).ReadToEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task XmlSerializerOutputFormatterIsCalled()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_services, _app);
|
||||||
|
var client = server.Handler;
|
||||||
|
var headers = new Dictionary<string, string[]>();
|
||||||
|
headers.Add("Accept", new string[] { "application/xml;charset=utf-8" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.SendAsync("POST",
|
||||||
|
"http://localhost/XmlSerializer/GetDummyClass?sampleInput=10", headers, null, null);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
Assert.Equal(200, response.StatusCode);
|
||||||
|
Assert.Equal("<DummyClass xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||||
|
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
||||||
|
new StreamReader(response.Body, Encoding.UTF8).ReadToEnd());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -73,10 +73,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
setup.Setup(mvcOptions);
|
setup.Setup(mvcOptions);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Equal(3, mvcOptions.OutputFormatters.Count);
|
Assert.Equal(5, mvcOptions.OutputFormatters.Count);
|
||||||
Assert.IsType<NoContentFormatter>(mvcOptions.OutputFormatters[0].Instance);
|
Assert.IsType<NoContentFormatter>(mvcOptions.OutputFormatters[0].Instance);
|
||||||
Assert.IsType<TextPlainFormatter>(mvcOptions.OutputFormatters[1].Instance);
|
Assert.IsType<TextPlainFormatter>(mvcOptions.OutputFormatters[1].Instance);
|
||||||
Assert.IsType<JsonOutputFormatter>(mvcOptions.OutputFormatters[2].Instance);
|
Assert.IsType<JsonOutputFormatter>(mvcOptions.OutputFormatters[2].Instance);
|
||||||
|
Assert.IsType<XmlDataContractSerializerOutputFormatter>(mvcOptions.OutputFormatters[3].Instance);
|
||||||
|
Assert.IsType<XmlSerializerOutputFormatter>(mvcOptions.OutputFormatters[4].Instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -12,5 +12,11 @@ namespace FormatterWebSite.Controllers
|
||||||
{
|
{
|
||||||
return Content(dummyObject.SampleInt.ToString());
|
return Content(dummyObject.SampleInt.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public DummyClass GetDummyClass(int sampleInput)
|
||||||
|
{
|
||||||
|
return new DummyClass { SampleInt = sampleInput };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// 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 Microsoft.AspNet.Mvc;
|
||||||
|
|
||||||
|
namespace FormatterWebSite
|
||||||
|
{
|
||||||
|
public class XmlSerializerController : Controller
|
||||||
|
{
|
||||||
|
public override void OnActionExecuted(ActionExecutedContext context)
|
||||||
|
{
|
||||||
|
var result = context.Result as ObjectResult;
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
result.Formatters.Add(new XmlSerializerOutputFormatter());
|
||||||
|
}
|
||||||
|
|
||||||
|
base.OnActionExecuted(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public DummyClass GetDummyClass(int sampleInput)
|
||||||
|
{
|
||||||
|
return new DummyClass { SampleInt = sampleInput };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue