diff --git a/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/SerializableErrorWrapper.cs b/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/SerializableErrorWrapper.cs
index d247b2fab9..e8a28f576f 100644
--- a/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/SerializableErrorWrapper.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Formatters.Xml/SerializableErrorWrapper.cs
@@ -14,6 +14,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
[XmlRoot("Error")]
public sealed class SerializableErrorWrapper : IXmlSerializable, IUnwrappable
{
+ // Element name used when ModelStateEntry's Key is empty. Dash in element name should avoid collisions with
+ // other ModelState entries because the character is not legal in an expression name.
+ private static readonly string EmptyKey = "MVC-Empty";
+
// Note: XmlSerializer requires to have default constructor
public SerializableErrorWrapper()
{
@@ -63,6 +67,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
{
var key = XmlConvert.DecodeName(reader.LocalName);
var value = reader.ReadInnerXml();
+ if (string.Equals(EmptyKey, key, StringComparison.Ordinal))
+ {
+ key = string.Empty;
+ }
SerializableError.Add(key, value);
reader.MoveToContent();
@@ -81,6 +89,11 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
{
var key = keyValuePair.Key;
var value = keyValuePair.Value;
+ if (string.IsNullOrEmpty(key))
+ {
+ key = EmptyKey;
+ }
+
writer.WriteStartElement(XmlConvert.EncodeLocalName(key));
if (value != null)
{
@@ -102,4 +115,4 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
return SerializableError;
}
}
-}
\ No newline at end of file
+}
diff --git a/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Internal/SerializableErrorWrapperTests.cs b/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Internal/SerializableErrorWrapperTests.cs
index 2a6cfaf47d..ec0175b8df 100644
--- a/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Internal/SerializableErrorWrapperTests.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Formatters.Xml.Test/Internal/SerializableErrorWrapperTests.cs
@@ -6,7 +6,6 @@ using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using Microsoft.AspNetCore.Mvc.ModelBinding;
-using Microsoft.AspNetCore.Testing;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
@@ -28,8 +27,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
public void WrappedSerializableErrorInstance_ReturnedFromProperty()
{
// Arrange
- var serializableError = new SerializableError();
- serializableError.Add("key1", "key1-error");
+ var serializableError = new SerializableError
+ {
+ { "key1", "key1-error" }
+ };
// Act
var wrapper = new SerializableErrorWrapper(serializableError);
@@ -57,7 +58,10 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
{
// Arrange
var serializableErrorXml = "" +
- "Test Error 1 Test Error 2Test Error 3";
+ "Test error 0" +
+ "Test Error 1 Test Error 2" +
+ "Test Error 3" +
+ "Test Error 4";
var serializer = new DataContractSerializer(typeof(SerializableErrorWrapper));
// Act
@@ -66,8 +70,28 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
var errors = wrapper.SerializableError;
// Assert
- Assert.Equal("Test Error 1 Test Error 2", errors["key1"]);
- Assert.Equal("Test Error 3", errors["key2"]);
+ Assert.Collection(
+ errors,
+ kvp =>
+ {
+ Assert.Equal(string.Empty, kvp.Key);
+ Assert.Equal("Test error 0", kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal("key1", kvp.Key);
+ Assert.Equal("Test Error 1 Test Error 2", kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal("key2", kvp.Key);
+ Assert.Equal("Test Error 3", kvp.Value);
+ },
+ kvp =>
+ {
+ Assert.Equal("list[3].key3", kvp.Key);
+ Assert.Equal("Test Error 4", kvp.Value);
+ });
}
[Fact]
@@ -75,11 +99,18 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
{
// Arrange
var modelState = new ModelStateDictionary();
+ modelState.AddModelError(string.Empty, "Test error 0");
modelState.AddModelError("key1", "Test Error 1");
modelState.AddModelError("key1", "Test Error 2");
modelState.AddModelError("key2", "Test Error 3");
+ modelState.AddModelError("list[3].key3", "Test Error 4");
var serializableError = new SerializableError(modelState);
var outputStream = new MemoryStream();
+ var expectedContent = "" +
+ "Test error 0" +
+ "Test Error 1 Test Error 2" +
+ "Test Error 3" +
+ "Test Error 4";
// Act
using (var xmlWriter = XmlWriter.Create(outputStream))
@@ -91,15 +122,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml.Internal
var res = new StreamReader(outputStream, Encoding.UTF8).ReadToEnd();
// Assert
- var expectedContent =
- TestPlatformHelper.IsMono ?
- "Test Error 1 Test Error 2" +
- "Test Error 3" :
- "" +
- "Test Error 1 Test Error 2Test Error 3";
-
Assert.Equal(expectedContent, res);
}
}
-}
\ No newline at end of file
+}