From d2db7b82f177dcadc57d60ad02905020dba53deb Mon Sep 17 00:00:00 2001 From: "kotov.a" Date: Tue, 10 Dec 2019 10:20:17 +0300 Subject: [PATCH] DataContract containing IList produces invalid WSDL #346 --- .../Wsdl/Services/IStructsService.cs | 36 +++++++++++++++++++ src/SoapCore.Tests/Wsdl/WsdlTests.cs | 21 +++++++++++ src/SoapCore/Meta/MetaWCFBodyWriter.cs | 19 +++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/SoapCore.Tests/Wsdl/Services/IStructsService.cs diff --git a/src/SoapCore.Tests/Wsdl/Services/IStructsService.cs b/src/SoapCore.Tests/Wsdl/Services/IStructsService.cs new file mode 100644 index 00000000..425f2193 --- /dev/null +++ b/src/SoapCore.Tests/Wsdl/Services/IStructsService.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.ServiceModel; +using System.Text; + +namespace SoapCore.Tests.Wsdl.Services +{ + [ServiceContract] + public interface IStructsService + { + [OperationContract] + void Method(StructService.StructModel model); + } + + public class StructService : IStructsService + { + public void Method(StructModel model) + { + throw new NotImplementedException(); + } + + [DataContract] + public struct AnyStruct + { + public int Prop { get; set; } + } + + [DataContract] + public class StructModel + { + [DataMember] + public IList MyStructs { get; set; } + } + } +} diff --git a/src/SoapCore.Tests/Wsdl/WsdlTests.cs b/src/SoapCore.Tests/Wsdl/WsdlTests.cs index d3179aeb..576f08bf 100644 --- a/src/SoapCore.Tests/Wsdl/WsdlTests.cs +++ b/src/SoapCore.Tests/Wsdl/WsdlTests.cs @@ -91,6 +91,27 @@ public void CheckNonNullableEnum() simpleTypeElements.ShouldNotBeEmpty(); } + [TestMethod] + public void CheckStructsInList() + { + StartService(typeof(StructService)); + var wsdl = GetWsdl(); + StopServer(); + var root = XElement.Parse(wsdl); + var elementsWithEmptyName = GetElements(root, _xmlSchema + "element").Where(x => x.Attribute("name")?.Value == string.Empty); + elementsWithEmptyName.ShouldBeEmpty(); + + var elementsWithEmptyType = GetElements(root, _xmlSchema + "element").Where(x => x.Attribute("type")?.Value == "xs:"); + elementsWithEmptyType.ShouldBeEmpty(); + + var structTypeElement = GetElements(root, _xmlSchema + "complexType").Single(x => x.Attribute("name")?.Value == "AnyStruct"); + var annotationNode = structTypeElement.Descendants(_xmlSchema + "annotation").SingleOrDefault(); + var isValueTypeElement = annotationNode.Descendants(_xmlSchema + "appinfo").Descendants(XNamespace.Get("http://schemas.microsoft.com/2003/10/Serialization/") + "IsValueType").SingleOrDefault(); + Assert.IsNotNull(isValueTypeElement); + Assert.AreEqual("true", isValueTypeElement.Value); + Assert.IsNotNull(annotationNode); + } + [TestMethod] public void CheckStreamDeclaration() { diff --git a/src/SoapCore/Meta/MetaWCFBodyWriter.cs b/src/SoapCore/Meta/MetaWCFBodyWriter.cs index 246a8e84..1115d9b2 100644 --- a/src/SoapCore/Meta/MetaWCFBodyWriter.cs +++ b/src/SoapCore/Meta/MetaWCFBodyWriter.cs @@ -718,6 +718,18 @@ private void WriteComplexType(XmlDictionaryWriter writer, Type type) writer.WriteAttributeString("name", toBuildName); writer.WriteAttributeString("xmlns:ser", SERIALIZATION_NS); + if (type.IsValueType && ResolveSystemType(type).name == null) + { + writer.WriteStartElement("xs:annotation"); + writer.WriteStartElement("xs:appinfo"); + writer.WriteStartElement("IsValueType"); + writer.WriteAttributeString("xmlns", SERIALIZATION_NS); + writer.WriteValue(true); + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteEndElement(); + } + var hasBaseType = HasBaseType(type); if (hasBaseType) @@ -1024,11 +1036,16 @@ private void AddSchemaType(XmlDictionaryWriter writer, Type type, string name, b xsTypename = $"{(sysType.ns == SERIALIZATION_NS ? "ser" : "xs")}:{sysType.name}"; writer.WriteAttributeString("nillable", "true"); } - else + else if (ResolveSystemType(type).name != null) { var sysType = ResolveSystemType(type); xsTypename = $"{(sysType.ns == SERIALIZATION_NS ? "ser" : "xs")}:{sysType.name}"; } + else + { + var ns = $"q{_namespaceCounter++}"; + xsTypename = $"{ns}:{typeName}"; + } } writer.WriteAttributeString("minOccurs", "0");