This particular serialization problem took 2 midnight sessions to sort out. We had some untyped orchs published as webservices inside the service boundary and we were building a strong typed ASMX gateway as the service boundary. We used WSCF to generate the ASMX and used all the schemas that were inside the orchestrations so that we didnt have to maintain two different sets of messages. We then came across 2 problems, the first one more easily solved than the other. I'll explain them below
(1)Duplicate namespaces: When you define a set of schemas in Biztalk, it is perfectly acceptable to define a common target namespace for example http://mycompany/schemas/services/customerservice and then to have different messages with specific root elements such as CreateCustomer, UpdateCustomer and so on. When biztalk recieves the message and validates them and works out the subscriptions, it adds the root element onto the target namespace making it http://mycompany/schemas/services/customerservice#CreateCustomer (note the # before the suffix) and this is enough for it to resolve most schemas. However, if you put all these Create, Update and Delete methods in your ASMX, then when you add a web reference, the .NET system crashes complaining of duplicate namespaces. Actually, the WSCF tool complained about duplicate namespaces even while creating the ASMX so we bypassed it and coded the ASMX ourselves (not realising it was right in complaining). This stumped us for a while, but it looks like this is default behavior in .NET and Biztalk has the ability to handle it but not the normal .NET framework which is fine. So we worked around it by changing the targetNamespace in all our schemas to have some extra phrases such as create, update and delete. Of course, if you put these kind of suffixes into the targetNamespace for biztalk its not a problem at all and it is then guaranteed to work in ordinary ASMX as well.
(2) Serialization and Precompilation: The second problem was much more involved. Once we finished revising the namespaces, we called the webservice only to get a nasty error message saying "File not found exception. System cannot find the file "xyz123".dll (some arbitrary constantly changing name) . We tried setting all sorts of permissions everywhere and it didnt solve the problem. We narrowed it down to the serializer since ordinary webservice calls not involving complex types were working fine and since the webservice was writing to our debug log files we knew that the system wasnt even invoking the webservice. Finally we saw a post where someone recommended that we use Chris Sells' XmlPrecompiler tool and the associated GUI built by Matthew Nolton. We then used the WSCF tool to generate a bunch of classes corresponding to the schema and checked them out. By this time i had also narrowed down the problem to a particular set of webmethods and one in particular where returning a void worked fine but returning a strong type caused the crash. Now the tool worked perfectly and crashed at the offending type. On close examination we found that by mistake, someone had created an array of arrays. (ie) we were returning an element called References and in that we needed unbounded elements named Reference with some attributes. It turned out that References had also been declared as unbounded. To add to this the namespaces were a bit muddled up and i read an article on MSDN saying that unqualified attributes in array types cause problems (or something to that effect). Anyway, i basically rewrote the schema to ensure all the elements were qualified correctly, corrected the 'unbounded' element and then it worked fine. There were also other schemas that dealt with arrays where the namespaces had to be reworked, but in the end it all worked fine.
This is a problem that one doesnt mind spending a couple of late nights working through eh? Who would have thought it would come down to finding a precompilation tool and sorting out the bug. So there it is... be very careful with schema definitions and arrays and use the precompiler tool as part of your quality checks. It will save a lot of tears and gain you some sleep as well.
Whew.. this is a record for me. Two posts in the same day. Well, it has been a rather busy weekend trying to sort out my new laptop and make some progress on a serialisation issue i've been having. Thought i'd post about it cos it might make interesting reading for any Biztalkers in a similar situation out there. It also looks like this issue is still floating around on newsgroup posts (in fact I just came across my post on this subject last year and nothing much has happened since then).
[Update: Since this post, I've managed to solve the problem. So i've done an edit to put in the resolution]
Heres the situation
(1) You publish an orchestration as a webservice. The schema of the message is fully qualified
(2) You submit data via a . NET component. In the processing of serialising data you use the correct namespaces in the XmlSerializer.
(3) The orchestration recieves the data and throws an exception since the ns0: prefix is missing from the root element although it is there as a prefix for the main namespace (ie) it is there in xmlns:ns0="xyz".
A similar problem exists when you send data from inside Biztalk to an external component and find that the XML cannot be deserialised into the corresponding class because the parser crashes when it sees the ns0:.
So what do you do? Some people have a separate message for the webservice which has no targetNamespace at all and then manage to map it into a a more strongly qualified message in the orchestration. The problem i had last year was that when we opened the map again it threw all sorts of weird script errors and sometimes wouldnt compile. At that point we were sending data to an external system so we had to resort to a hack. We changed the component to accept an XmlDocument and then wrote another little helper to strip out the ns0 and sent the message on. This worked fine, but its a hack and i still find it distasteful.
Today Im in the situation where i need to submit data via a strong typed webservice to an untyped ASMX sitting on top of an orchestration.Sending the data to the strong typed facade is not a problem. But from there, I need to send it to the XmlDocument interface and just serialising the recieved object with a correct namespace doesnt solve the problem because we cannot prefix with ns0.
Resolution: To solve this we had to revisit the namespace declarations and ensure that all elements were prefixed correctly. Additionally, in Biztalk we had to make sure that the schemas were set to Elements - Qualified and Attributes- Unqualified. In a couple of our schemas the targetNamespace was redefined in another part with another prefix. All of this contributed to Biztalk not understanding the schema. When you send data to an external webservice, if you import the webreference, Biztalk creates the necessary schemas so all we need to do is map our internal message to the WS message and if there are prefixed elements in the schema definition, they will be prefixed in the transmitted message. If you are sending serialised data into an untyped message (Xmldocument input) or where the webservice takes a string as input (debatable practice, I know!!) , then the ns0: will go across in all the elements. However, if you use the same XSD on the other end, then you shouldnt have a problem in deserialising the data. In our old project, there was probably some foul up in the recipient schema which caused the serialisation problem. Its also worth experimenting more with XmlNameTables and suchlike to ensure the elements get mapped correctly.
Hope this helps someone in a similar situation.