diff --git a/src/SoapCore.Tests/RawRequestSoap12Tests.cs b/src/SoapCore.Tests/RawRequestSoap12Tests.cs
index 565657a0..d9d84afe 100644
--- a/src/SoapCore.Tests/RawRequestSoap12Tests.cs
+++ b/src/SoapCore.Tests/RawRequestSoap12Tests.cs
@@ -46,6 +46,56 @@ public void Soap12PingWithActionInHeader()
}
}
+ [TestMethod]
+ public void Soap12PingWithNamespaceDeclarationsRepeatedOnBody()
+ {
+ var body = @"
+
+
+
+ abc
+
+
+
+";
+ var bodyBytes = Encoding.UTF8.GetBytes(body);
+ using (var host = CreateTestHost())
+ using (var client = host.CreateClient())
+ using (var content = new StringContent(body, Encoding.UTF8, "application/soap+xml"))
+ {
+ content.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("action", "\"http://tempuri.org/ITestService/Ping\""));
+ using (var res = host.CreateRequest("/Service.svc").And(msg => msg.Content = content).PostAsync().Result)
+ {
+ res.EnsureSuccessStatusCode();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void Soap12PingWithPrefixShadowedOnBody()
+ {
+ var body = @"
+
+
+
+ abc
+
+
+
+";
+ var bodyBytes = Encoding.UTF8.GetBytes(body);
+ using (var host = CreateTestHost())
+ using (var client = host.CreateClient())
+ using (var content = new StringContent(body, Encoding.UTF8, "application/soap+xml"))
+ {
+ content.Headers.ContentType.Parameters.Add(new System.Net.Http.Headers.NameValueHeaderValue("action", "\"http://tempuri.org/ITestService/Ping\""));
+ using (var res = host.CreateRequest("/Service.svc").And(msg => msg.Content = content).PostAsync().Result)
+ {
+ res.EnsureSuccessStatusCode();
+ }
+ }
+ }
+
[TestMethod]
public void Soap12PingWithActionInEnvelopeHeader()
{
@@ -253,8 +303,8 @@ public async Task Soap12DetailedFault()
ExceptionProperty = "Detail message"
});
}
- }
-
+ }
+
[TestMethod]
public async Task Soap12InvalidSchema()
{
diff --git a/src/SoapCore/ParsedMessage.cs b/src/SoapCore/ParsedMessage.cs
index ba8159d7..c3695fb6 100644
--- a/src/SoapCore/ParsedMessage.cs
+++ b/src/SoapCore/ParsedMessage.cs
@@ -188,9 +188,12 @@ private static (XDocument, bool isEmpty) ExtractSoapBody(XDocument envelope, Mes
return (new XDocument(), true);
}
- var rootAttributes = root.Attributes();
+ // The envelope attributes are carried onto the body so that it keeps its namespace bindings once it is
+ // detached. An attribute the body already declares has to win: XAttribute does not override equality, so
+ // Union compares by reference and a declaration present on both elements would be added twice and throw.
var bodyAttributes = bodyNode.Attributes();
- var allAttributes = bodyAttributes.Union(rootAttributes);
+ var rootAttributes = root.Attributes().Where(attribute => bodyNode.Attribute(attribute.Name) == null);
+ var allAttributes = bodyAttributes.Concat(rootAttributes).ToList();
bodyNode.ReplaceAttributes(allAttributes);
//return new XDocument(bodyNode.Elements().FirstOrDefault());