question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Breaking changes in SoapSerializer.XmlSerializer for previously generated ASMX client code

See original GitHub issue

I have legacy ASMX webservices, which are being used by some third-party stakeholders, who we cannot control. So our ultimate goal is to migrate .NET 4.7.2 solution to .NET 6 without (major) breaking changes for our clients. SoapCore looked like a savior here, and it was really promising when we were prototyping it with some basic web services. However testing it in our main solution - there are some corner cases, which we cannot to find a way how to workaround.

1. Guid[] type in requests object in a legacy solution was specified as “ArrayOfGuid” complex type. It was looking like this (here and below - WSDL definition is truncated for brevity, but I can provide a full one if it would help):

<s:complexType name="GetPricesRequest">
    <s:sequence>
        <s:element minOccurs="0" maxOccurs="1" ref="s1:Product"/>
        <s:element minOccurs="0" maxOccurs="1" name="ProductIds" type="tns:ArrayOfGuid"/>
    </s:sequence>
</s:complexType>
<s:complexType name="ArrayOfGuid">
    <s:sequence>
        <s:element minOccurs="0" maxOccurs="unbounded" name="guid" type="s2:guid"/>
    </s:sequence>
</s:complexType>

<s:schema elementFormDefault="qualified" targetNamespace="http://microsoft.com/wsdl/types/">
    <s:simpleType name="guid">
        <s:restriction base="s:string">
            <s:pattern value="[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"/>
        </s:restriction>
    </s:simpleType>
</s:schema>

With SoapCore, using XmlSerializer - it’s just “ArrayOfString”:

<xsd:complexType name="GetPricesRequest">
    <xsd:sequence>
        <xsd:element minOccurs="0" maxOccurs="1" name="Product" type="tns:ProductDto"/>
        <xsd:element minOccurs="0" maxOccurs="1" name="ProductIds" type="tns:ArrayOfString"/>
    </xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ArrayOfString">
    <xsd:sequence>
        <xsd:element minOccurs="0" maxOccurs="unbounded" name="string" type="xsd:string"/>
    </xsd:sequence>
</xsd:complexType>

As the result, using that client - it fails to map, and webservices receives an empty array. Is it by design, is it a configuration issue, or some potential missing feature? Any ideas where we could look at in case we would like to contribute with some pull-request?

2. Another issue with same contract is with XmlElement attributes usage. We have the following request object with a complex type inside:

[XmlType(Namespace = "urn:Bbb.Services.Management")]
public class GetPricesRequest
{
    [XmlElement("Product", Namespace = "urn:Bbb.Services.Common")]
    public ProductDto Product { get; set; }

    public Guid[] ProductIds { get; set; }
}

In a legacy solution it was looking like this:

<s:element name="Product" type="s1:ProductDto"/>
<s:complexType name="ProductDto">
    <s:sequence>
        <s:element minOccurs="1" maxOccurs="1" name="Id" type="s2:guid"/>
        <s:element minOccurs="0" maxOccurs="1" name="Name" type="s:string"/>
        <s:element minOccurs="0" maxOccurs="1" name="Type" type="s:string"/>
    </s:sequence>
</s:complexType>

In new one there is something completely broken, it returns invalid WSDL, with duplicated elements, which cannot be consumed (note how name="Product" is duplicated):

<xsd:element minOccurs="0" maxOccurs="1" name="Product" type="tns:ProductDto"/>
<xsd:complexType name="ProductDto">
<xsd:sequence>
    <xsd:element minOccurs="0" maxOccurs="1" name="Product" type="xsd:string"/>
    <xsd:element minOccurs="0" maxOccurs="1" name="Product" type="xsd:string"/>
    <xsd:element minOccurs="1" maxOccurs="1" name="Product" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>

If I drop XmlElement attribute - it produces a valid WSDL, but it still cannot be consumed by legacy clients (due to the first issue, and due to breaking change). I won’t advocate, that it was correctly configured in our legacy solution, but it was working like that for years. (If it was a bug, it was used as a feature.😃 ) Any ideas how we could workaround it, or at least minimize possible breaking changes?

Update: my intermediate achievement - old clients are working, but new ones are failing to map request parameters correctly (webservice receives empty parameters). 🤷‍♂️ It was achieved by leaving XmlElement without “ElementName”, just with “Namesapce”.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:10 (6 by maintainers)

github_iconTop GitHub Comments

1reaction
andersjonssoncommented, Sep 22, 2022

If you’re only having issue with newly generated clients then I believe a focus on WSDL differences is the correct approach.

There is an option to use a file as your WSDL https://github.com/DigDes/SoapCore#using-with-external-wsdl--xsd-schemas

Try using the legacy WSDL this way, and see if newly generated clients work. If you then feel like making it work with the WSDL generated by SoapCore, remove differences from the file until you find the culprit (for example, remove the “schema” bit and see if it stops working). Then support could be added for the critical bits.

0reactions
Aleksanderiscommented, Sep 26, 2022

So, seems like external WSDL schemas support are fully enough for us, since we are not planning to add any new features to our legacy ASMX web services. Thanks for pointing it out once again! 👍 I said fully, but actually there were some missing options. 😃 It kind of was working, but some additional workarounds were needed (like duplicated endpoints with different paths for same webservice). As promised about contributing to this project, I created my first pull-request with potential improvements - https://github.com/DigDes/SoapCore/pull/904. Will see how it goes, but I hope someone manages to review it and move further. 😃

(The mentioned pull-request is not to fix this issue, but perhaps others would be able to solve similar issues in a similar way.)

Read more comments on GitHub >

github_iconTop Results From Across the Web

Deserialization of ASMX web service failing partially
Ok i solved it but its really screwy. What happened is the "Add service reference" generated code contains a namespace aka [System.
Read more >
NET 6 XmlSerializer no longer emits line breaks #64885
This appears to be a behavioural regression in .NET 6 in the way XML is serialized. The following code no longer produces the...
Read more >
XML Serialization with XML Web Services
XML serialization is the underlying transport mechanism used in the XML Web services architecture, performed by the XmlSerializer class.
Read more >
Chapter 32: Web Service Standards and Extensions
This chapter describes two most important web service protocols: SOAP and WSDL. SOAP is an incredibly lightweight protocol for messaging.
Read more >
Secure Web Services via Message oriented Middleware
Describes an approach for delivery of Soap Messages serialised using ASP.NET Web Client Services over MSMQ and MQ.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found