-
Notifications
You must be signed in to change notification settings - Fork 379
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
Breaking changes in SoapSerializer.XmlSerializer for previously generated ASMX client code #903
Comments
Your first issue could probably be partly solved by adding your own type. Something like
} As far as I know there is no support for adding a pattern to a string, but this way you'll get the correct type name in the wsdl. For your second problem I think that it's a straight up bug. Most likely it uses the attribute from the property for the members in the complextype as well. That is obviously wrong. Same deal here, if you feel like fixing it a PR would be more than welcome! This is, btw, the same way that I started contributing to the project. I ran across bugs and missing features when I was migrating a large legacy service where breaking changes wasn't an option |
Thanks for suggestions. I cloned the repository, added a direct reference to it from my project and was trying to debug all day long today to understand how it works and how it could be improved. So far creating custom type to cover [XmlType(Namespace = "urn:Bbb.Services.Management")]
public class GetPricesRequest
{
[XmlElement("Product", Namespace = "urn:Bbb.Services.Common")]
public ProductDto Product { get; set; }
public GuidList ProductIds { get; set; }
}
[XmlType(TypeName = "ArrayOfGuid")]
public class GuidList : List<Guid>
{
} Tried different combinations, and it was either old client wasn't working or a newly generated one was not working. Regarding the issue about duplicated element names for complex types marked with AddSchemaType(writer, toBuild, parentTypeToBuild.ChildElementName ?? member.Name, isArray: createListWithoutProxyType, isListWithoutWrapper: createListWithoutProxyType, isUnqualified: isUnqualified);
So even if these changes would work for me after some more digging, I'm not really sure if it won't break some other cases. |
Some more findings - after digging a bit more, seems like mapping/deserializing is failing due to additional namespace used, which is specified with [XmlElement("Product", Namespace = "urn:Bbb.Services.Common")] In a legacy ASMX implementation these additional schemas are added into WSDL like this (note <wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
xmlns:tns="urn:Bbb.Services.Management"
xmlns:s2="http://microsoft.com/wsdl/types/"
xmlns:s1="urn:Bbb.Common" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="urn:Bbb.Services.Management">
<wsdl:types>
<s:schema elementFormDefault="qualified" targetNamespace="urn:Bbb.Services.Management">
...
</s:schema>
<s:schema elementFormDefault="qualified" targetNamespace="urn:Bbb.Common">
...
</s:schema>
<s:schema elementFormDefault="qualified" targetNamespace="http://microsoft.com/wsdl/types/">
...
</s:schema>
</wsdl:types>
<wsdl:message name="...">
...
</wsdl:message>
<wsdl:message name="...">
...
</wsdl:message>
</wsdl:definitions> After request is created, it's created like this - note additional <request xmlns="urn:Bbb.Services.Management">
<Product xmlns="urn:Bbb.Common">
<Id>aaa</Id>
<Name>ddd</Name>
<Type>ccc</Type>
</Product>
<ProductIds>
<guid>44643eb1-3f76-4c1c-a672-402ae8085934</guid>
<guid>c84ae939-adf8-4cce-a468-13c3014c73ca</guid>
</ProductIds>
</request> With SoapCore these additional schemas are not included in the WSDL and then Any ideas if it's possible to add additional namespaces/schemas to WSDL? Or maybe it's not really necessary and something else could be enough? We have a full control over server side code - we can alter I found these "secret" flags in the code - https://github.com/DigDes/SoapCore/blob/develop/src/SoapCore/Meta/BodyWriterExtensions.cs#L17 |
In general I've found that the wsdl is not super important when it comes to supporting old clients. I don't know of any way to add additional namespaces to the WSDL, but I think you will be fine if you can manage to add it to the response payload. I think the namespace Property in XmlTypeAttribute works. Perhaps try to add that to "Product"?
Any PR's you would like to contribute towards making your use case work would be welcome. That way SoapCore gets better for all users 😄 |
Yeah, I also realized this fact, that WSDL is not super important for old clients. However I'm still not sure how it works in general - like maybe same logic is used for WSDL and then for deserialization. I.e. if WSDL is wrongly generated, then it might be there is same reason why requests are failing as well. Regarding [XmlType(TypeName = "Product", Namespace = "urn:Bbb.Common", IncludeInSchema = true)] I'm not against any PR's, and not waiting that someone fix these issues for me - but at this moment I'm a bit too far away of understanding how it should work, and what was the reasoning for some already partially included but disabled features. :) |
I'm new to this project, but I think most contributions have been made to fix a particular issue. Probably there was an ambition to add support, but the person never got around to finishing it. In WriteParameterElement I can see that the namespace property of XmlElement is passed into the AddSchemaType method SoapCore/src/SoapCore/Meta/MetaBodyWriter.cs Lines 273 to 288 in 162f502
However, in AddSchemaTypePropertyOrField the namespace property is not used. Maybe that is the reason why your namespaces doesn't appear in the WSDL? I can't find any traces of it when it comes to serialization though. For deserialization there is the DeserializeArrayXmlSerializer method that does some "manual" things. Might be worth checking out if you're having issues there. |
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 Try using the legacy WSDL this way, and see if newly generated clients work. |
Hmm, that sounds interesting. I will try that external WSDL schemas option. Thanks for pointing out! |
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! 👍 (The mentioned pull-request is not to fix this issue, but perhaps others would be able to solve similar issues in a similar way.) |
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):
With SoapCore, using XmlSerializer - it's just "ArrayOfString":
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:
In a legacy solution it was looking like this:
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):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".The text was updated successfully, but these errors were encountered: