views:

50

answers:

1

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"&gt;
 <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:

  1. why isn’t my client seeing the contents of the reply document?

  2. how do I fix it?

  3. 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);
A: 

After the namespace was added I had to change it to this:

You don't seem to add any namespace here...... try adding the default namespace to the constructor of the XmlSerializer like this:

XmlSerializer serializer = new XmlSerializer(typeof(get_dataEur), "http://www.company.com/ecommerce"
);
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);

Does that help??

marc_s
That sounds good in principle however I am having trouble testing it. I didn't mention that the client is in a SQL CLR assembly. Having added the default namespace to the constructor of the XmlSerializer I am now getting a new error running the client:A .NET Framework error occurred during execution of user-defined routine or aggregate "EurECommerce_SendData": System.Exception: System.InvalidOperationException: Cannot load dynamically generated serialization assembly.....I have spent the whole day reading posts about this error and trying the solutions but nothing has worked.
Laurence
I think this new error deserves its own write-up on StackOverflow. If I can get it resolved I'll come back here and test this suggestion.
Laurence