Wcf: Incorrect generated client, two-dimensional array generated in place of list (WCF Connected Services)

Created on 9 Jun 2016  路  24Comments  路  Source: dotnet/wcf

Hacked WSDL: https://gist.github.com/Ravenheart/dc92c2023d3536798aca3e721f5a85ae

In relation to https://github.com/dotnet/wcf/issues/1269 I've had some help from the company that made the service and they created a special version that doesn't have endless recursion possible. Now this new version is added successfully to a sample project BUT the actual generated code throws a runtime exception.

System.AggregateException: One or more errors occurred. (System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e is not assignable from System.String[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.) ---> System.InvalidOperationException: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e is not assignable from System.String[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.
   at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass1_0.<CreateGenericTask>b__0(IAsyncResult asyncResult)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at TestConsoleNETCore.Program.Main(String[] args) in D:\DEV\TestConsoleNETCore\src\TestConsoleNETCore\Program.cs:line 17
---> (Inner Exception #0) System.InvalidOperationException: System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e is not assignable from System.String[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e.
   at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass1_0.<CreateGenericTask>b__0(IAsyncResult asyncResult)<---

The error in question is related to complex types that may end up with properties like "public string[][] SomeProperty" and according to some googling around this is also a bug with .NET's tooling (tested it with wsdl.exe, svcutil.exe and the new connected services util).

Generated client: https://gist.github.com/Ravenheart/b33e79eba6519088731804b11d8bb6bd

Usage:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace TestConsoleNETCore
{
    public class Program
    {
        public static void Main(string[] args)
        {
            try
            {
                PISServiceWS.PISWebServiceClient client = new PISServiceWS.PISWebServiceClient();

                //exception here
                var res = client.vldContractAsync(new PISServiceWS.vldContractIn()
                {
                    Item = "8610166253",
                    ItemElementName = PISServiceWS.ItemChoiceType9.egn,

                    issueDate = new DateTime(2016, 6, 6),
                    issueDateSpecified = true,

                    practiceNo = "2211131508",
                    specCode = "01",
                    uin = "0500000012",
                }).Result;

                Console.WriteLine(res.vldContractOut.vld);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}
Backlog bug tooling

Most helpful comment

@Ravenheart
The generated code for the two dimensional array tr is not correct. In XmlArrayItemAttribute, we need either use typeof(string[]) or add NestingLevel=1. We'll look at the root cause.

To work around this issue now, you can edit the generated code and make the change yourself as below.
[System.Xml.Serialization.XmlArrayAttribute(Order=1)]
[System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string), IsNullable=false)]
public string[][] tr {}

Either use
[System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string[]), IsNullable=false)]
Or
[System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string), IsNullable=false, NestingLevel=1)]

All 24 comments

Just to help out a bit, in the linked generated client the class that is problematic is:

    [System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "0.2.0.0")]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://pis.technologica.com/ws/")]
    public partial class table
    {

        private string[] hrField;

        private string[][] trField;

        /// <remarks/>
        [System.Xml.Serialization.XmlArrayAttribute(Order=0)]
        [System.Xml.Serialization.XmlArrayItemAttribute("hd", IsNullable=false)]
        public string[] hr
        {
            get
            {
                return this.hrField;
            }
            set
            {
                this.hrField = value;
            }
        }

        /// <remarks/>
        [System.Xml.Serialization.XmlArrayAttribute(Order=1)]
        [System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string), IsNullable=false)]
        public string[][] tr
        {
            get
            {
                return this.trField;
            }
            set
            {
                this.trField = value;
            }
        }
    }

THe field/property "private string[][] trField;", the class is supposed to represent a sort of DataTable with a variable amount of columns (hrField are the column names, trField are the actual rows).

Thanks @Ravenheart for reporting the issue. We are looking into this.

@Ravenheart
The generated code for the two dimensional array tr is not correct. In XmlArrayItemAttribute, we need either use typeof(string[]) or add NestingLevel=1. We'll look at the root cause.

To work around this issue now, you can edit the generated code and make the change yourself as below.
[System.Xml.Serialization.XmlArrayAttribute(Order=1)]
[System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string), IsNullable=false)]
public string[][] tr {}

Either use
[System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string[]), IsNullable=false)]
Or
[System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string), IsNullable=false, NestingLevel=1)]

No problems @huanwu I've had this hacked working since 2013 (only updated the WSDL recently for some new features).

@huanwu is there anything more we need to do about this issue? Can this be closed?

@hongdai could you please log a bug in VSTS to see if we can fix this in WCF Connected Service?

VSTS bug is logged.

We got another hit of the issue. See https://github.com/dotnet/wcf/issues/2219

@petervestergaard reported the same issue in #2219

I also experienced this issue, maybe more examples won't help anymore, but just thought I'd share in case mine is different.

This WSDL segment:

<xs:element maxOccurs="unbounded" minOccurs="0" name="applicantGroup">
    <xs:complexType>
        <xs:sequence>
            <xs:element maxOccurs="2" name="applicant" type="ApplicantType"/>
        </xs:sequence>
    </xs:complexType>
</xs:element>

Generated this property:

[System.Xml.Serialization.XmlArrayAttribute(Order=1)]
[System.Xml.Serialization.XmlArrayItemAttribute("applicant", typeof(ApplicantType), IsNullable=false)]
public ApplicantType[][] applicantGroup
{
    get
    {
        return this.applicantGroupField;
    }
    set
    {
        this.applicantGroupField = value;
    }
}

Which caused the following error:

System.Xml: Unable to generate a temporary class (result=1).
error CS0030: Cannot convert type 'ServiceReference.ApplicantType[]' to 'ServiceReference.ApplicantType'
error CS0029: Cannot implicitly convert type 'ServiceReference.ApplicantType' to 'ServiceReference.ApplicantType[]'

Changing the typeof(ApplicantType) to typeof(ApplicantType[]) resolved this for me.

@hongdai @zhenlan Is there any movement on this topic? This defect dates back two years but is still an issue when generating bindings.

Hi @ipjohnson
We will hopefully look into this in the next sprint.
thanks

I guess it's in xsd.exe as well, not just svcutil, ran xsd on AudDataTypes.xsd from the url https://www.vwe.nl/Developers, I ended up with

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.xmlmode.nl/interdata/aud")]
    public partial class audaconInfoIntervalTypeV1 {

        private intervalItem[][] intervallenField;

        /// <remarks/>
        [System.Xml.Serialization.XmlArrayItemAttribute("interval", typeof(intervalItem), IsNullable=false)]
        public intervalItem[][] intervallen {
            get {
                return this.intervallenField;
            }
            set {
                this.intervallenField = value;
            }
        }
    }

What I wanted was somthing like this, or at least something that works out of the box:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://www.xmlmode.nl/interdata/aud")]
    public partial class audaconInfoIntervalTypeV1 {

        private intervallen[] intervallenField;

        /// <remarks/>
        [System.Xml.Serialization.XmlElementAttribute("intervallen")]
        public intervallen[] intervallen
        {
            get
            {
                return this.intervallenField;
            }
            set
            {
                this.intervallenField = value;
            }
        }
    }

I think @AndreSteenbergen is right. I just ran Xsd.exe on an XSD from German OpenImmo and tried to serialize it again. I ended up with te same error. If it helps I'll upload the XSD, generated CSharp class and the code I used. The XSD and generated CS are rather large so I'll wait for a reply first.

In addidition, the fix from @huanwu, adding the ',NestingLevel=1' was the fix for me.

[System.Xml.Serialization.XmlArrayItemAttribute("td", typeof(string), IsNullable=false, NestingLevel=1)]

I too am receiving this error.

The workaround proposed by @huanwu worked but only the one in which "NetstingLevel=1" was used. Excluding this property still produces the error.

I am getting this error in a different scenario. I have an XSD that specifies multiple options as part of a complex type with xsd:choice:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://ACORD.org/Standards/Life/2" targetNamespace="http://ACORD.org/Standards/Life/2" elementFormDefault="unqualified" attributeFormDefault="unqualified" version="2.25.00">
    <xsd:element name="OLifE" type="OLifE_Type"/>
    <xsd:complexType name="OLifE_Type">
        <xsd:sequence>
            <xsd:element ref="SourceInfo" minOccurs="0"/>
            <xsd:choice minOccurs="0" maxOccurs="unbounded">
                <xsd:element ref="Activity" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Grouping" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Holding" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="InvestProduct" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Party" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="PolicyProduct" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Relation" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Currency" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Criteria" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="FinancialStatement" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Scenario" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="FormInstance" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="SettlementInfo" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="DistributionAgreement" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="CommSchedule" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="SystemMessage" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Campaign" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="Case" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="CodeList" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="BusinessProcessDef" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="AuditEntry" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="UnderwritingGuidelines" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="KeyedValue" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element ref="OLifEExtension" minOccurs="0" maxOccurs="unbounded"/>
            </xsd:choice>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="SourceInfo" type="SourceInfo_Type"/>
    <xsd:complexType name="SourceInfo_Type">
        <xsd:sequence>
            <xsd:element ref="CreationDate" minOccurs="0"/>
            <xsd:element ref="CreationTime" minOccurs="0"/>
            <xsd:element ref="SourceInfoName" minOccurs="0"/>
            <xsd:element ref="SourceInfoDescription" minOccurs="0"/>
            <xsd:element ref="SourceInfoComment" minOccurs="0"/>
            <xsd:element ref="FileControlID" minOccurs="0"/>
            <xsd:element ref="KeyedValue" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element ref="OLifEExtension" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

This generates an Items object array for the xsd:choice property, which upon serialization yields the same error.
Using the following code yields the same error:

var toSerialize = new OLifE_Type {
    Items = new object[] {
        new SourceInfo_Type {
            SourceInfoComment = "something"
        }
    }
};
toSerialize.Serialize();

the Serialize implementation is nothing fancy. It throws the error at new System.Xml.Serialization.XmlSerializer(typeof(T)); where typeof(T) is the type of OLife_Type

Thank you for the feedback, but our team was unable to prioritize it at this time as they are working on problems with broader customer impact. This bug has existed in similar tools for a long time and there is a known work around.

It's incredible, but this compile error is still there in 2020 !!!!

I'm building a soap proxy for SalesForce web service, and the error is this (typeof need an array type):

        [System.Xml.Serialization.XmlArrayItemAttribute("columns", typeof(ListViewRecordColumn), IsNullable=false)]
        public ListViewRecordColumn[][] records;

must be

        [System.Xml.Serialization.XmlArrayItemAttribute("columns", typeof(ListViewRecordColumn[]), IsNullable=false)]
        public ListViewRecordColumn[][] records;

Do exist any workaround at compiler level except manually fixing it ?

@eng-marani its been there since the early 2000s :)

Well, what is Microsoft waiting for before fixing it ? The obsolescence of WebService technology ?
And why it has been marked as "closed" when it isn't at all ?

Same issue here, salesforce wants us to use Visual Studio 2003 or later. As far as I found Salesforce lightning API is not really useable for automatically creating leads and stuff, so I'm into the SOAP Api and ran into this error right away after generating the service reference and using it.

The real exception I get is at runtime: System.PlatformNotSupportedException: Compiling JScript/CSharp scripts is not supported #2219

and that workaround works but feels dirty

        MethodInfo method = typeof(XmlSerializer).GetMethod("set_Mode", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
        method.Invoke(null, new object[] { 1 });

Why is this closed and every linked issue closed as well? Using .net core 3.1

2021 and the bug is still around...
Our workaround was to add a optional 'dummy' element to the sequence in the 'container'-element in xsd so that the generator does not omit it as "not necessary?".

The Structure was something like that

<root>
    <container>
         <item/>
         <item/>
   </container>
   <container>
         <item/>
   </container>
</root>

svcutil generated a item[][] and as others already mentioned this generated proxy cannot be used afterwards.

Thank you for the feedback, but our team was unable to prioritize it at this time as they are working on problems with broader customer impact. This bug has existed in similar tools for a long time and there is a known work around.

@mlacouture @dasetser @HongGit @zhenlan @huanwu @hongdai @shmao

It's shameful that this bug has existed for so long and the "known workaround" recommended by Microsoft is to manually edit an auto-generated file! I'm in disbelief that you'd recommend manually editing a generated file and expect that to be acceptable and maintainable.

Why can't this be resolved correctly?

Was this page helpful?
0 / 5 - 0 ratings