We were given external SOAP services that we have to consume in our project. All of these provide WSDL data, but a lot of them are not .NET services (most of them were written in Java). We have generated a number of client proxies with wsdl.exe tool. This tool does what it's supposed to do, it creates proxies for us to consume.
The problem appears once we try to call methods on these services using generated proxies. We intercept all SOAP requests for logging purposes and XML data looks different from the one specified in WSDL schema.
For instance, if a field is called "Name", our proxies will serialize it as "nameField". I guess this is because the property called "Name" uses a backing field called "nameField". Services on the other side obviously can't interpret this kind of naming convention.
This wouldn't be happening if our ASMX proxies used the old XmlSerializer, but for some reason they opt for DataContractSerializer, which completely messes up serialization and breaks compatibility between clients and services.
My colleagues have resorted to manually constructing XML data and then sending it with HttpWebRequest class. I think this is completely unacceptable in 2011, this is what automated proxy generation is for.
My question is: why is this happening? Why are our proxies using DataContractSerializer and thus ignoring all xml serialization attributes in the process? Is there a way to force them to use XmlSerializer once again?
We use .NET 4.0.
If you are using WCF the default is DataContractSerializer. And if the types do not have explicit [DataContract]/[DataMember] markers, then DataContractSerializer will use the fields, which sounds like what is happening.
To use XmlSerializer instead, add [XmlSerializerFormat] to your service. See MSDN.
You could also try adding [XmlType] or [XmlRoot] to your classes (if it isn't already there).
Related
I'm going to develop a webservice (likely in WCF) and probably several parameters passed to the exposed methods will be custom type parameters.
Do you have any hints on how to avoid breaking SOA decoupling and reach my target?
Thanks!
WSDL defines interoperable contract with :
endpoint and action describing how to communicate with webservice
types using and xsd schema
The xml schema (xsd) describes types : xml elements, value types using xml types and so on.
So if you can describe all your types using Xml Schema, then it will be ok. .NET enforce your type can be serialized to xml, then it is possible to expose it via a webservice.
On the client side, there are often libraries which can read WSDL and deduct/generate classes in their language to serialize/deserialize messages to/from the service. But any human can also read the contract and the writ
I need to develop a webservice which will be exposed to a java client over SOAP. We have a well defined schema in place which we use to communicate between both the systems. Now I need to expose an operation on my WCF contract which takes the Schema object and store it inside our DB.
I have followed the following for developing the webservice.
Host it over basichttp in wcf
Create an object model of the schema using xsd.exe
Take the schema as a parameter on the operation something like DoThis(SchemaObject schema)
Since this is going to be exposed in WCF, I have gone and modified the xsd tool generated object model. Our schema has mutiple level of nesting, and is a combination of 4 different schema linked together. The object graph generated by xsd tool has abstract classes, inheritence etc.
For this to work, I have gone and defined DataContract attrbute on everyclass and added the namespace to it, which was already there in the XmlTypeAttribute. Also I have added DataMemebers to each properties.
Some of the properties in the schema are arrays which was defined by the tool using xmlarrayitem attribute.
Now when I send a request using SOAP UI, the object is not getting deserialized as expected. Almost all the fields are coming as null, which has some sort of inheritence hierarchy. I have added KnownType attribute to the appropriate datacontracts, but still not working.
My question is:
Is this the right way to develop a webservice.
Is there a way to avoid putting the datacontract and data members and just work witht he serialization attributes added by the xsd tool?
Is it necessary to use datacontract attribute, will it not work with the xmlserialization attributes as it works inthe case xml deserialization?
WCF supports two types of serialization - DataContractSerializer and XmlSerializer.
XSD.exe generates strong type entities with all necessary XmlSerializer attributes. You do not need to add any DataContract or DataMemeber attributes to work with generated classes in WCF.
See MSDN for more details - http://msdn.microsoft.com/en-us/library/ms733901.aspx
Be also very careful with your entities generated by xsd.exe. As you probably already seen WCF server will eat many serialization changes you can do in these files but that will be breaking change for clients because they relay on XSD.
If possible I would remain these auto-generated entities without changes to guarantee that interface is not broken. You may introduce separate DTO classes for using in Business Layer. You can implement inheritence hierarchy over there.
Bunch of Unit Tests can help if you feel that auto-generated classes need to be changed. These Test Cases should generate different data sets, serialize them into XML and check that XML over XSD.
Technically, I don't see any particular flaw in the way you are implementing the service.
But from the architectural point of view it's too complicated for me. It's always easier to send 'flat' data-structures and hide complexity somewhere else.
I would suggest the following steps
Develop some special 'transport' scheme, maximally flattening it. It makes changes of the service easier when your model changes. And also it makes less painful to generate and cope with xsd.
Code special transformators on both sides of the channel to translate normal model to 'flat' and then vice-versa.
We have an existing .net 3.5 WCF service with which PreserveObjectReferences is set to true on the server side.
When PreserveObjectReferences is set to false BizTalk can consume the response.
Is there a way to get BizTalk to consume the PreserveObjectReferences response payloads...
PreserveObjectReferences manifests itself with a z:id occurring for the first instance of an object and a z:ref occurring for any subsequent object occurrences:
<b:xyz *z:Id="5"* i:type="abc">...</b:xyz>
...
<b:xyz *z:ref="5"* />
What was the option PreserveObjectReferences configured to when generating the xsd's?
The xsd's are generated from the WCF service it's WSDL and if in this WSDL these extra attributes are not defined BizTalk won't know they exist and BizTalk will throw an exception. I don't know for sure if the DataContractSerializer will inlude these attributes when generating a WSDL. If the DataContractSerializer doesn't include these attributes while generating a WSDL you must change the xsd of the response message to allow xs:any attributes on the elements where these attributes are added.
Both BizTalk and JAX-B have issues with dealing with the payload for differing reasons. ID/IDREF are supported XML Schema options but every implementation seems to have problems consuming them.
For JAX-B when both idref and nil=true is specified it is unable to marshall the payload into objects:
<b:xyz z:ref="5" nil="true" />
Removal of the nil=true or setting preserve object references to false (i.e not returning a a payload utilising the idref capability means that Java coders can work around this.
BizTalk can work around this by re-hydrating the xml without the idref support through xslt transforms or other means.
Our solution to both was to ensure preserve object references was turned off. both systems were then able to integrate without significant hassle.
I have an AXIS2/JAX-WS web service using a code first implementation (yes I know, that is bad). The web service is being consumed by a .NET based client.
Before we had Axis1, and when custom objects were passed between the client and the server, the client and the server code had to do their own serialization and de-serialization.
When we converted to Axis2, we removed the custom serialization and converted all objects to the regular bean format.
Now here comes the problem, the original way that objects were sent was through polymorphic calls, but there appears to be a problem with the way that Axis2/JAX-WS and .NET handle serialization. I believe that .NET uses the xsi:type attribute when declaring the element and the java side changes the element type. Is there a way to make polymorphic calls to web services using a .NET client and a Java based webservice?
Thanks.
Found out the problem. The java classes needed to have their namespaces defined with the #XmlType annotation. Now the objects are getting serlialized and deserialized correctly.
When an object is serialized (by remoting to be sent across the wire) does the instance method code get serialized? Or are just the class level instance fields serialized?
I am asking this as some of my objects have large method and want to know wheather I should be using DTO's (data transfer objects) for sending data across the wire.
I guessing it's just the data plus some type version data ... am I right?
Thanks
Methods are never serialized.
Re "fields" - it all depends on the serializer; BinaryFormatter will do fields; you mention "remoting", which suggests BinaryFormatter, but remoting is largely a hangover now - from MSDN (on remoting):
This topic is specific to a legacy
technology that is retained for
backward compatibility with existing
applications and is not recommended
for new development. Distributed
applications should now be developed
using the Windows Communication
Foundation (WCF).
If you use web-services or WCF: XmlSerializer does public fields+properties; DataContractSerializer will do marked fields, etc.
Regular classes are often reusable as DTOs, but if you need lots of control over the wire (or have versioning issues), a separate DTO can be helpful.
(edit/additional) note also that there are other reasons not to like BinaryFormatter - it can be very brittle with versioning, and very painful to fix (although achievable). Other (more tolerant) serializers exist if this is likely to be an issue... if so, let me know and I'll update.
What gets saved is the data plus tags corresponding to your class and property names. The code itself doesn't get serialized.