Client no longer getting data from Web Service after introducing targetNamespace in XSD
Posted
by Laurence
on Stack Overflow
See other posts from Stack Overflow
or by Laurence
Published on 2010-03-10T18:44:13Z
Indexed on
2010/05/13
19:04 UTC
Read the original article
Hit count: 356
Sorry if there is way too much info in this post – there’s a load of story before I get to the actual problem. I thought I‘d include everything that might be relevant as I don’t have much clue what is wrong.
I had a working web service and client (both written with VS 2008 in C#) for passing product data to an e-commerce site. The XSD started like this:
<xs:schema id="Ecommerce"
elementFormDefault="qualified"
xmlns:mstns="http://tempuri.org/Ecommerce.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="eur">
<xs:complexType>
<xs:sequence>
<xs:element ref="sec" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
etc
Here’s a sample document sent from client to service:
<eur xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" class="ECommerce_WebService" type="product" method="GetLastDateSent" chunk_no="1" total_chunks="1" date_stamp="2010-03-10T17:16:34.523" version="1.1">
<sec guid="BFBACB3C-4C17-4786-ACCF-96BFDBF32DA5" company_name="Company" version="1.1">
<data />
</sec>
</eur>
Then, I had to give the service a targetNamespace. Actually I don’t know if I “had” to set it, but I added (to the same VS project) some code to act as a client to a completely unrelated service (which also had no namespace), and the project would not build until I gave my service a namespace.
Now the XSD starts like this:
<xs:schema id="Ecommerce"
elementFormDefault="qualified"
xmlns:mstns="http://tempuri.org/Ecommerce.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.company.com/ecommerce"
xmlns:ecom="http://www. company.com/ecommerce">
<xs:element name="eur">
<xs:complexType>
<xs:sequence>
<xs:element ref="ecom:sec" minOccurs="1" maxOccurs="1" />
</xs:sequence>
etc
As you can see above I also updated all the xs:element ref attributes to give them the “ecom” prefix. Now the project builds again.
I found the client needed some modification after this. The client uses a SQL stored procedure to generate the XML. This is then de-serialised into an object of the correct type for the service’s “get_data” method. The object’s type used to be “eur” but after updating the web reference to the service, it became “get_dataEur”. And sure enough the parent element in the XML had to be changed to “get_dataEur” to be accepted. Then bizarrely I also had to put the xmlns attribute containing my namespace on the “sec” element (the immediate child of the parent element) rather than the parent element. Here’s a sample document now sent from client to service:
<get_dataEur xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" class="ECommerce_WebService" type="product" method="GetLastDateSent" chunk_no="1" total_chunks="1" date_stamp="2010-03-10T18:23:20.653" version="1.1">
<sec xmlns="http://www.company.com/ecommerce" guid="BFBACB3C-4C17-4786-ACCF-96BFDBF32DA5" company_name="Company" version="1.1">
<data />
</sec>
</get_dataEur>
If in the service’s get_data method I then serialize the incoming object I see this (the parent element is “eur” and the xmlns attribute is on the parent element):
<eur xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.company.com/ecommerce" class="ECommerce_WebService" type="product" method="GetLastDateSent" chunk_no="1" total_chunks="1" date_stamp="2010-03-10T18:23:20.653" version="1.1">
<sec guid="BFBACB3C-4C17-4786-ACCF-96BFDBF32DA5" company_name="Company" version="1.1">
<data />
</sec>
</eur>
The service then prepares a reply to go back to the client. The XML looks like this (the important data being sent back is the date_stamp attribute in the last_sent element):
<eur xmlns="http://www.company.com/ecommerce" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" class="ECommerce_WebService" type="product" method="GetLastDateSent" chunk_no="1" total_chunks="1" date_stamp="2010-03-10T18:22:57.530" version="1.1">
<sec version="1.1" xmlns="">
<data>
<last_sent date_stamp="2010-02-25T15:15:10.193" />
</data>
</sec>
</eur>
Now finally, here’s the problem!!! The client does not see any data – all it sees is the parent element with nothing inside it. If I serialize the reply object in the client code it looks like this:
<get_dataResponseEur xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" class="ECommerce_WebService" type="product" method="GetLastDateSent" chunk_no="1" total_chunks="1" date_stamp="2010-03-10T18:22:57.53" version="1.1" />
So, my questions are:
why isn’t my client seeing the contents of the reply document?
how do I fix it?
why do I have to put the xmlns attribute on a child element rather than the parent element in the outgoing document?
Here’s a bit more possibly relevant info:
The client code (pre-namespace) called the service method like this:
XmlSerializer serializer = new XmlSerializer(typeof(eur));
XmlReader reader = xml.CreateReader();
eur eur = (eur)serializer.Deserialize(reader);
service.Credentials = new NetworkCredential(login, pwd);
service.Url = url;
rc = service.get_data(ref eur);
After the namespace was added I had to change it to this:
XmlSerializer serializer = new XmlSerializer(typeof(get_dataEur));
XmlReader reader = xml.CreateReader();
get_dataEur eur = (get_dataEur)serializer.Deserialize(reader);
get_dataResponseEur eur1 = new get_dataResponseEur();
service.Credentials = new NetworkCredential(login, pwd);
service.Url = url;
rc = service.get_data(eur, out eur1);
© Stack Overflow or respective owner