Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue With Data Types when using XmlSerializer #959

Closed
jspmu opened this issue Sep 11, 2023 · 7 comments · Fixed by #960
Closed

Issue With Data Types when using XmlSerializer #959

jspmu opened this issue Sep 11, 2023 · 7 comments · Fixed by #960

Comments

@jspmu
Copy link

jspmu commented Sep 11, 2023

Hi All,

We are using XmlSerializer and an old version of SoapCore(v1.1.0.9) as below to create our soap service, however when we add a reference to this on visual studio the object definitions appear malformed.
Some examples are byte[] File and string FileName properties end up on the client side as byte[][] File and string[] FileName respectively.

<wsdl:definitions targetNamespace="http://stepXpress.com/services" name="IWebService">
<wsdl:types>
<xsd:schema elementFormDefault="qualified" targetNamespace="http://webService.com/services">
<xsd:import namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
<xsd:import namespace="http://schemas.datacontract.org/2004/07/System"/>
...
<xsd:element minOccurs="0" maxOccurs="unbounded" name="File" type="xsd:base64Binary"/>
<xsd:element minOccurs="0" maxOccurs="unbounded" name="FileName" type="xsd:string"/>
            app.UseSoapEndpoint<IStepXWebService>(
                "/StepXWebService.asmx",
                new BasicHttpBinding
                {
                    MaxReceivedMessageSize = int.MaxValue,
                    MaxBufferPoolSize = int.MaxValue,
                    ReaderQuotas = XmlDictionaryReaderQuotas.Max,
                    TextEncoding = new UTF8Encoding(false)
                },
                serializer: SoapSerializer.XmlSerializer,
                caseInsensitivePath: true
            );

Additionally I have updated to the latest version of SoapCore (v.1.1.0.38) with the startup and have this same issue.

            app.UseSoapEndpoint<IStepXWebService>(
                "/StepXWebService.asmx",
                new SoapEncoderOptions(),
                SoapSerializer.XmlSerializer
            );

An example of the reference.cs that is generated by visual studio:

private byte[][] fileField;

[System.Xml.Serialization.XmlElementAttribute("File", DataType="base64Binary", Order=1)]
public byte[][] File {
    get {
        return this.fileField;
    }
    set {
        this.fileField = value;
        this.RaisePropertyChanged("File");
    }
}

Is there something that can be done to prevent this from happening while still using the XmlSerializer?

It is important to us that we don't break compatibility for existing Web Services clients.

All help is greatly appreciated.

@andersjonsson
Copy link
Collaborator

That seems very odd. When I generate a client for my own legacy service, also in Visual studio, strings are strings. I don't have any byte arrays so I can't be sure about that one. In my experience existing clients can work fine even though a newly generated one is wonky. But this is unlike anything I've encountered.

Are you using a custom wsdl?

From one of my own generated classes (Reference.cs)

private string descriptionField;

[System.Xml.Serialization.XmlElementAttribute(Order=5)]
public string Description
{
   get
   {
       return this.descriptionField;
   }
   set
   {
       this.descriptionField = value;
   }
}

@andersjonsson
Copy link
Collaborator

I use the overload of UseSoapEndpoint that accepts a SoapCoreOptions, but I find it hard to believe that this should affect the client generation in Visual studio

@jspmu
Copy link
Author

jspmu commented Sep 13, 2023

I have made a minimal reproduction and it appears that the reason that this is caused was from an XmlElement attribute on the objects

public class FinishedResponse
{
   [XmlElement(ElementName = "file")]
   public byte[] File { get; set; }

   [XmlElement(ElementName = "fileName")]
   public string FileName { get; set; }
}

Once these are removed the data types on the client are correctly byte[] and string

@andersjonsson
Copy link
Collaborator

I have made a minimal reproduction and it appears that the reason that this is caused was from an XmlElement attribute on the objects

public class FinishedResponse
{
   [XmlElement(ElementName = "file")]
   public byte[] File { get; set; }

   [XmlElement(ElementName = "fileName")]
   public string FileName { get; set; }
}

Once these are removed the data types on the client are correctly byte[] and string

Ah! Then there is most likely a bug in there somewhere. XmlElement has a Type-property that you can probably use to be able to use XmlElement

andersjonsson added a commit to andersjonsson/SoapCore that referenced this issue Sep 13, 2023
…t C# sees as enumerable. They should not be unbounded in the wsdl since that would cause clients to generate byte[] as byte[][] etc.

fixes DigDes#959
@andersjonsson
Copy link
Collaborator

Could you pull my fork https://github.com/andersjonsson/SoapCore/tree/fix-wsdl-error-for-string-and-bytearray and test this against your service to see if it works?

@jspmu
Copy link
Author

jspmu commented Sep 15, 2023

Hi @andersjonsson

Thank you for finding the fix to that issue - I have been able to test and verify that this has worked successfully.

I have found one other issue with the xml serializer that I missed previously because of this issue which I assume is unrelated

I have tried supplying the type of Guid as part of thexml element, however with or without this addition when the a new service refrence is added in visual studio the type is always guid.

On the old wsdl the type was successfully set as xs:guid.
I have tried modifying the ClrTypeResolver line 35:

    case "Guid":
	return "guid";

and while this did output type xsd:guid on the wsdl, when a new reference was added it was typed as string not guid

[XmlElement(ElementName = "sessionGuid", Type = typeof(Guid))]
public Guid SessionGuid { get; set; }

Is this something you might be able to help with?

@andersjonsson
Copy link
Collaborator

As far as I can tell Guid is not part of the types that are supported by Soap.
If visual studio can generate references with real guid types there has got to be something else in the wsdl, other than the type attribute, since you already tested that.

Please open a new issue, since this one i resolved, and include relevant parts of your old and new wsdl and I'll try to investigate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants