Changes to introduce CanWriteResult for Xml OutputFormatters.
This commit is contained in:
parent
041d350d51
commit
b9f1586008
|
|
@ -2,11 +2,8 @@
|
|||
// 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.Text;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Xml;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
@ -17,6 +14,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
public static readonly int DefaultMaxDepth = 32;
|
||||
|
||||
#if NET45
|
||||
public static readonly XsdDataContractExporter XsdDataContractExporter = new XsdDataContractExporter();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default Reader Quotas for XmlReader.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,25 @@ namespace Microsoft.AspNet.Mvc
|
|||
encoding = encoding ?? SupportedEncodings.FirstOrDefault();
|
||||
return encoding;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the object to be serialized.
|
||||
/// </summary>
|
||||
/// <param name="context">The context which contains the object to be serialized.</param>
|
||||
/// <returns>The type of the object to be serialized.</returns>
|
||||
public virtual Type GetObjectType([NotNull] OutputFormatterContext context)
|
||||
{
|
||||
if (context.DeclaredType == null)
|
||||
{
|
||||
if (context.Object != null)
|
||||
{
|
||||
return context.Object.GetType();
|
||||
}
|
||||
}
|
||||
|
||||
return context.DeclaredType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool CanWriteResult(OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,9 +37,25 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// </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)
|
||||
public override object CreateSerializer([NotNull] Type type)
|
||||
{
|
||||
return new DataContractSerializer(type);
|
||||
DataContractSerializer serializer = null;
|
||||
try
|
||||
{
|
||||
#if NET45
|
||||
// Verify that type is a valid data contract by forcing the serializer to try to create a data contract
|
||||
FormattingUtilities.XsdDataContractExporter.GetRootElementName(type);
|
||||
#endif
|
||||
// If the serializer does not support this type it will throw an exception.
|
||||
serializer = new DataContractSerializer(type);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// We do not surface the caught exception because if CanWriteResult returns
|
||||
// false, then this Formatter is not picked up at all.
|
||||
}
|
||||
|
||||
return serializer;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -51,7 +67,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||
using (var xmlWriter = CreateXmlWriter(response.Body, tempWriterSettings))
|
||||
{
|
||||
var dataContractSerializer = CreateDataContractSerializer(context.DeclaredType);
|
||||
var dataContractSerializer = (DataContractSerializer)CreateSerializer(GetObjectType(context));
|
||||
dataContractSerializer.WriteObject(xmlWriter, context.Object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.AspNet.Mvc.HeaderValueAbstractions;
|
||||
|
|
@ -28,6 +29,27 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// </summary>
|
||||
public XmlWriterSettings WriterSettings { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a serializer to serialzie the particualr type.
|
||||
/// </summary>
|
||||
/// <param name="type">The type which needs to be serialized.</param>
|
||||
/// <returns>The serializer object.</returns>
|
||||
public abstract object CreateSerializer(Type type);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool CanWriteResult([NotNull] OutputFormatterContext context, MediaTypeHeaderValue contentType)
|
||||
{
|
||||
if (base.CanWriteResult(context, contentType))
|
||||
{
|
||||
if (CreateSerializer(GetObjectType(context)) != null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default XmlWriterSettings.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -37,9 +37,21 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// </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)
|
||||
public override object CreateSerializer([NotNull] Type type)
|
||||
{
|
||||
return new XmlSerializer(type);
|
||||
XmlSerializer serializer = null;
|
||||
try
|
||||
{
|
||||
// If the serializer does not support this type it will throw an exception.
|
||||
serializer = new XmlSerializer(type);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// We do not surface the caught exception because if CanWriteResult returns
|
||||
// false, then this Formatter is not picked up at all.
|
||||
}
|
||||
|
||||
return serializer;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -51,7 +63,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
tempWriterSettings.Encoding = context.SelectedEncoding;
|
||||
using (var xmlWriter = CreateXmlWriter(response.Body, tempWriterSettings))
|
||||
{
|
||||
var xmlSerializer = CreateXmlSerializer(context.DeclaredType);
|
||||
var xmlSerializer = (XmlSerializer)CreateSerializer(GetObjectType(context));
|
||||
xmlSerializer.Serialize(xmlWriter, context.Object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
// 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.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -180,6 +182,18 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void XmlDataContractSerializer_CanWriteResult_ReturnsTrue_ForWritableType()
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new XmlDataContractSerializerOutputFormatter(
|
||||
XmlOutputFormatter.GetDefaultXmlWriterSettings());
|
||||
var outputFormatterContext = GetOutputFormatterContext(null, typeof(Dictionary<string, string>));
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(formatter.CanWriteResult(outputFormatterContext, MediaTypeHeaderValue.Parse("application/xml")));
|
||||
}
|
||||
|
||||
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
|
||||
string contentType = "application/xml; charset=utf-8")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@
|
|||
// 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.Http;
|
||||
using Microsoft.AspNet.Mvc.HeaderValueAbstractions;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -173,6 +175,30 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
Assert.True(outputFormatterContext.ActionContext.HttpContext.Response.Body.CanRead);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void XmlSerializer_CanWriteResult_ReturnsFalse_ForNonWritableType()
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new XmlSerializerOutputFormatter();
|
||||
var outputFormatterContext = GetOutputFormatterContext(outputValue: null,
|
||||
outputType: typeof(Dictionary<string, string>));
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(formatter.CanWriteResult(outputFormatterContext, MediaTypeHeaderValue.Parse("application/xml")));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void XmlDataContractSerializer_CanWriteResult_ReturnsTrue_ForWritableType()
|
||||
{
|
||||
// Arrange
|
||||
var formatter = new XmlSerializerOutputFormatter();
|
||||
var outputFormatterContext = GetOutputFormatterContext(outputValue: null,
|
||||
outputType: typeof(string));
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(formatter.CanWriteResult(outputFormatterContext, MediaTypeHeaderValue.Parse("application/xml")));
|
||||
}
|
||||
|
||||
private OutputFormatterContext GetOutputFormatterContext(object outputValue, Type outputType,
|
||||
string contentType = "application/xml; charset=utf-8")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -62,5 +62,26 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><SampleInt>10</SampleInt></DummyClass>",
|
||||
new StreamReader(response.Body, Encoding.UTF8).ReadToEnd());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task XmlSerializerFailsAndDataContractSerializerIsCalled()
|
||||
{
|
||||
// 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/DataContractSerializer/GetPerson?name=HelloWorld", headers, null, null);
|
||||
|
||||
//Assert
|
||||
Assert.Equal(200, response.StatusCode);
|
||||
Assert.Equal("<Person xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\" " +
|
||||
"xmlns=\"http://schemas.datacontract.org/2004/07/FormatterWebSite\">" +
|
||||
"<Name>HelloWorld</Name></Person>",
|
||||
new StreamReader(response.Body, Encoding.UTF8).ReadToEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,12 +4,12 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"ActivatorWebSite": "",
|
||||
"AntiForgeryWebSite": "",
|
||||
"BasicWebSite": "",
|
||||
"CompositeViewEngine": "",
|
||||
"ConnegWebsite": "",
|
||||
"FormatterWebSite": "",
|
||||
"FormatterWebSite": "",
|
||||
"InlineConstraintsWebSite": "",
|
||||
"AntiForgeryWebSite": "",
|
||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||
"Microsoft.AspNet.PipelineCore": "1.0.0-*",
|
||||
"Microsoft.AspNet.Mvc.TestConfiguration": "",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
// 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
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for DataContractSerializerController
|
||||
/// </summary>
|
||||
public class DataContractSerializerController : Controller
|
||||
{
|
||||
public override void OnActionExecuted(ActionExecutedContext context)
|
||||
{
|
||||
var result = context.Result as ObjectResult;
|
||||
if (result != null)
|
||||
{
|
||||
result.Formatters.Add(new XmlSerializerOutputFormatter());
|
||||
result.Formatters.Add(new XmlDataContractSerializerOutputFormatter());
|
||||
}
|
||||
|
||||
base.OnActionExecuted(context);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public Person GetPerson(string name)
|
||||
{
|
||||
// The XmlSerializer should skip and the
|
||||
// DataContractSerializer should pick up this output.
|
||||
return new Person(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// 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.Runtime.Serialization;
|
||||
|
||||
namespace FormatterWebSite
|
||||
{
|
||||
[DataContract]
|
||||
public class Person
|
||||
{
|
||||
public Person(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue