抱歉,如果这篇文章中有太多信息 - 在我解决实际问题之前有很多故事。我想我会包括所有可能相关的内容,因为我不知道出了什么问题。
我有一个有效的 Web 服务和客户端(均使用 VS 2008 用 C# 编写)用于将产品数据传递到电子商务网站。XSD 是这样开始的:
<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
这是从客户端发送到服务的示例文档:
<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>
然后,我必须给服务一个 targetNamespace。实际上我不知道我是否“必须”设置它,但我添加(到同一个 VS 项目)一些代码作为客户端到一个完全不相关的服务(也没有命名空间),并且项目不会构建直到我给我的服务一个命名空间。
现在 XSD 是这样开始的:
<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
正如您在上面看到的,我还更新了所有 xs:element ref 属性,为它们赋予“ecom”前缀。现在项目再次构建。
我发现客户在此之后需要进行一些修改。客户端使用 SQL 存储过程来生成 XML。然后将其反序列化为服务“get_data”方法的正确类型的对象。该对象的类型曾经是“eur”,但在更新对服务的 Web 引用后,它变成了“get_dataEur”。果然,必须将 XML 中的父元素更改为“get_dataEur”才能被接受。然后奇怪的是,我还不得不将包含我的命名空间的 xmlns 属性放在“sec”元素(父元素的直接子元素)而不是父元素上。这是现在从客户端发送到服务的示例文档:
<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>
如果在服务的 get_data 方法中我序列化传入的对象,我会看到这个(父元素是“eur”,xmlns 属性在父元素上):
<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>
然后,该服务准备回复以返回给客户端。XML 看起来像这样(发回的重要数据是 last_sent 元素中的 date_stamp 属性):
<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>
现在终于,问题来了!!!客户端看不到任何数据——它看到的只是父元素,里面什么都没有。如果我在客户端代码中序列化回复对象,它看起来像这样:
<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" />
所以,我的问题是:
为什么我的客户看不到回复文档的内容?
我如何解决它?
为什么我必须将 xmlns 属性放在子元素上,而不是传出文档中的父元素上?
这里有一些更可能相关的信息:
客户端代码(前命名空间)调用服务方法,如下所示:
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);
添加命名空间后,我不得不将其更改为:
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);