Skip to content

Commit

Permalink
Merge pull request #1045 from Yozer/base-classes
Browse files Browse the repository at this point in the history
feat(wsdl-meta): add support to WSDL for base types
  • Loading branch information
andersjonsson committed May 28, 2024
2 parents 5346da7 + 553e2fb commit dbc8525
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 5 deletions.
33 changes: 33 additions & 0 deletions src/SoapCore.Tests/Wsdl/Services/IComplexBaseTypeService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.ServiceModel;

namespace SoapCore.Tests.Wsdl.Services;

[ServiceContract]
public interface IComplexBaseTypeService
{
[OperationContract]
DerivedTypeList Method(DerivedTypeList argument);
}

public class ComplexBaseTypeService : IComplexBaseTypeService
{
public DerivedTypeList Method(DerivedTypeList argument)
{
return new DerivedTypeList();
}
}

public class BaseType
{
public string BaseName { get; set; }
}

public class DerivedType : BaseType
{
public string DerivedName { get; set; }
}

public class DerivedTypeList : List<DerivedType>
{
}
24 changes: 24 additions & 0 deletions src/SoapCore.Tests/Wsdl/WsdlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1174,6 +1174,30 @@ public async Task CheckDataContractKnownTypeAttributeServiceWsdl()
Assert.IsNotNull(schemaElement.XPathSelectElement("//xsd:element[@name='ComplexInheritanceModelInputB' and @type='tns:ComplexInheritanceModelInputB']", nm));
}

[TestMethod]
public void CheckComplexBaseTypeServiceWsdl()
{
StartService(typeof(ComplexBaseTypeService));
var wsdl = GetWsdlFromAsmx();
StopServer();
Assert.IsNotNull(wsdl);

var root = XElement.Parse(wsdl);
var nm = Namespaces.CreateDefaultXmlNamespaceManager(false);

var derivedTypeContent = root.XPathSelectElement("//xsd:complexType[@name='DerivedType']/xsd:complexContent[@mixed='false']/xsd:extension[@base='tns:BaseType']/xsd:sequence/xsd:element[@name='DerivedName' and @type='xsd:string' and not(@nillable)]", nm);
Assert.IsNotNull(derivedTypeContent);

var baseTypeContent = root.XPathSelectElement("//xsd:complexType[@name='BaseType']/xsd:sequence/xsd:element[@name='BaseName' and @type='xsd:string' and not(@nillable)]", nm);
Assert.IsNotNull(baseTypeContent);

var listDerivedTypeMethodResponse = root.XPathSelectElement("//xsd:element[@name='MethodResponse']/xsd:complexType/xsd:sequence/xsd:element[@name='MethodResult' and @type='tns:ArrayOfDerivedType' and @nillable='true']", nm);
Assert.IsNotNull(listDerivedTypeMethodResponse);

var listDerivedType = root.XPathSelectElement("//xsd:complexType[@name='ArrayOfDerivedType']/xsd:sequence/xsd:element[@name='DerivedType' and @type='tns:DerivedType' and @nillable='true' and @minOccurs='0' and @maxOccurs='unbounded']", nm);
Assert.IsNotNull(listDerivedType);
}

[TestCleanup]
public void StopServer()
{
Expand Down
11 changes: 7 additions & 4 deletions src/SoapCore/Meta/BodyWriterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ public static string GetSerializedTypeName(this Type type)
{
var namedType = type;
bool isNullableArray = false;
var isGenericType = type.IsGenericType;
var isBaseTypeGeneric = type.BaseType is { IsGenericType: true };

if (type.IsArray)
{
namedType = type.GetElementType();
Expand All @@ -207,9 +210,9 @@ public static string GetSerializedTypeName(this Type type)
isNullableArray = true;
}
}
else if (typeof(IEnumerable).IsAssignableFrom(type) && type.IsGenericType)
else if (typeof(IEnumerable).IsAssignableFrom(type) && (isGenericType || isBaseTypeGeneric))
{
namedType = GetGenericType(type);
namedType = isGenericType ? GetGenericType(type) : GetGenericType(type.BaseType);
var underlyingType = Nullable.GetUnderlyingType(namedType);
if (underlyingType != null)
{
Expand All @@ -225,9 +228,9 @@ public static string GetSerializedTypeName(this Type type)
typeName = xmlTypeAttribute.TypeName;
}

if (type.IsArray || (typeof(IEnumerable).IsAssignableFrom(type) && type.IsGenericType))
if (type.IsArray || (typeof(IEnumerable).IsAssignableFrom(type) && (isGenericType || isBaseTypeGeneric)))
{
if (namedType.IsArray || (typeof(IEnumerable).IsAssignableFrom(type) && type.IsGenericType))
if (namedType.IsArray || (typeof(IEnumerable).IsAssignableFrom(type) && (isGenericType || isBaseTypeGeneric)))
{
typeName = GetSerializedTypeName(namedType);
}
Expand Down
32 changes: 31 additions & 1 deletion src/SoapCore/Meta/MetaBodyWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,15 @@ private void AddService(XmlDictionaryWriter writer)
}
}

private bool HasBaseType(Type type)
{
var isArrayType = type.IsArray || typeof(IEnumerable).IsAssignableFrom(type);

var baseType = type.GetTypeInfo().BaseType;

return !isArrayType && !type.IsEnum && !type.IsPrimitive && !type.IsValueType && baseType != null && !baseType.Name.Equals("Object");
}

private void AddSchemaComplexType(XmlDictionaryWriter writer, TypeToBuild toBuild)
{
var toBuildType = toBuild.Type;
Expand All @@ -762,6 +771,21 @@ private void AddSchemaComplexType(XmlDictionaryWriter writer, TypeToBuild toBuil
writer.WriteAttributeString("name", toBuildName);
}

var hasBaseType = HasBaseType(toBuildType);
if (hasBaseType)
{
writer.WriteStartElement("complexContent", Namespaces.XMLNS_XSD);

writer.WriteAttributeString("mixed", "false");

writer.WriteStartElement("extension", Namespaces.XMLNS_XSD);

var typeName = toBuildType.BaseType.GetSerializedTypeName();
writer.WriteAttributeString("base", $"tns:{typeName}");

_complexTypeToBuild.Enqueue(new TypeToBuild(toBuildType.BaseType));
}

if (toBuildType.IsArray)
{
writer.WriteStartElement("sequence", Namespaces.XMLNS_XSD);
Expand All @@ -779,7 +803,7 @@ private void AddSchemaComplexType(XmlDictionaryWriter writer, TypeToBuild toBuil
if (!isWrappedBodyType)
{
var propertyOrFieldMembers = toBuildBodyType.GetPropertyOrFieldMembers()
.Where(mi => !mi.IsIgnored()).ToList();
.Where(mi => !mi.IsIgnored() && mi.DeclaringType == toBuildType).ToList();

var elements = propertyOrFieldMembers.Where(t => !t.IsAttribute()).ToList();
if (elements.Any())
Expand Down Expand Up @@ -838,6 +862,12 @@ private void AddSchemaComplexType(XmlDictionaryWriter writer, TypeToBuild toBuil
}
}

if (hasBaseType)
{
writer.WriteEndElement(); // xs:extension
writer.WriteEndElement(); // xs:complexContent
}

writer.WriteEndElement(); // complexType

if (isWrappedBodyType)
Expand Down

0 comments on commit dbc8525

Please sign in to comment.