使用IXmlSerializable导出数据协定类型的WSDL / XSD架构

时间:2009-12-08 18:27:50

标签: .net wcf web-services serialization ixmlserializable

我正在创建一个我希望从Java应用程序中使用的WCF服务。但问题不在于.net-java interop。

关键点是与服务操作相关的类型之一是IXmlSerializable。该类型使用XmlSchemaProviderAttribute引用的静态方法返回其XSD架构。 问题是当我们通过mex-endpoint(http://..svc?wsdl)获得服务的wsdl时,不返回架构。

以下是详细信息。

一些wcf服务合同:

 [ServiceContract]
 public interface IService1
 {
  [OperationContract]
  DomainData GetData();
 }

DomainData类型是:

 [DataContract(Namespace = "http://schemas.biz.org/Samples/customserialization")]
 public class DomainData
 {
  [DataMember(Name = "AuxData")]
  Dictionary<String, AuxDomainData> m_auxData = new Dictionary<string, AuxDomainData>();

  [DataMember]
  public string ObjectId { get; set; }

  public IDictionary<string, AuxDomainData> AuxData
  {
   get { return m_auxData; }
  }
 }

如您所见,DomainData包含AuxDomainData对象的字典,即:

 [XmlSchemaProvider("GetXmlSerializationSchema")]
 public class AuxDomainData : IXmlSerializable
 {
  [DataMember]
  public Object AuxData { get; set; }

  XmlSchema IXmlSerializable.GetSchema() { return null; }

  void IXmlSerializable.ReadXml(XmlReader reader) { }

  void IXmlSerializable.WriteXml(XmlWriter writer) { }

  public static string Namespace = "http://schemas.biz.org/Samples/customserialization";

  public static XmlQualifiedName GetXmlSerializationSchema(XmlSchemaSet schemas)
  {
   var qname =  new XmlQualifiedName("AuxDomainData", Namespace);
   string resourceName = "CustomSerialization.aux-domain-data.xsd";
   using (Stream stream = typeof(AuxDomainData).Assembly.GetManifestResourceStream(resourceName))
   {
    var schema = XmlSchema.Read(stream, null);
    schemas.Add(schema);
   }
   return qname;
  }
 }

这里我们在GetXmlSerializationSchema方法中返回XSD架构。 架构本身很简单,但让我在这里跳过它。

我猜这段代码很简单,这是IXmlSerializable类型的常见场景。

现在,我们需要WSDL。我将在Metro的帮助下使用WSDL创建Java客户端 但实际上JDK 1.6就足够了,因为它包含WS堆栈(和wsimport.exe)。 所以java希望wsdl使用wsdl:service definition。这就是为什么我不能从wsdl.exe给它一个wsdl(因为wsdl生成的wsdl不包含wsdl:service定义,只包含wsdl:portType)。 所以,我打电话给wsimport.bat http://localhost/Service1.svc?wsdl

但我得到的是: [错误]未定义简单或复杂类型'q1:AuxDomainData'   http://locahost/CustomSerialization/Service1.svc?xsd=xsd3

的第1行

那是因为组合的wsdl实际上不包含AuxDomainData这样的类型。这是真的,我们不能责怪java / metro /任何其他堆栈。 如果我们看一下wcf生成的wsdl,它包含带有所有xsd模式导入的wsdl:types元素:

<wsdl:types>
  <xsd:schema targetNamespace="http://tempuri.org/Imports">
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd0" namespace="http://tempuri.org/" /> 
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" /> 
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd2" namespace="http://schemas.biz.org/Samples/customserialization" /> 
    <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd3" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays" /> 
  </xsd:schema>
</wsdl:types>

我不会在这里提供所有xsd,但关键是它们中有没有 AuxDomainData定义。 AuxDomainData类型的xsd-schema位于http://localhost/CustomSerialization/Service1.svc?xsd=xsd 4 “document”中。 但正如您所看到的,根wsdl不包含对它的引用。 那就是问题所在。结果wsdl / xsd架构设置不完整。

那么,我的选择是什么?

2 个答案:

答案 0 :(得分:0)

您确定WSDL没有引用它吗?通常,WCF将在&lt; wsdl:message&gt;列表之前包含一个元素。元素,有点像这样:

<wsdl:types>
    <xsd:schema targetNamespace="http://tempuri.org/Imports">
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd0" namespace="http://tempuri.org/"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/MyServiceNamespace"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd3" namespace="http://schemas.datacontract.org/2004/07/MyServiceNamespace.AnotherNamespace"/>
        <xsd:import schemaLocation="http://localhost/CustomSerialization/Service1.svc?xsd=xsd4" namespace="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
    </xsd:schema>
</wsdl:types>

检查一下。应该在那里。但是,Java可能无法识别它。

如果这是问题,那么有flatten the WSDL的方法。你可以尝试一下。

顺便说一句,mex端点通常是 Service1.svc / mex 。 WSDL略有不同。

答案 1 :(得分:0)

实际上,Aaron提出的“http://blogs.msdn.com/dotnetinterop/archive/2008/09/23/flatten-your-wsdl-with-this-custom-servicehost-for-wcf.aspx”解决方案变得不完全正确。 不是自己想法,而是代码。将ExportExtension用于多个服务后,请求wsdl进行下一步服务失败,原因是类型出版。

我也在msdn论坛上问过:http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/0ea27bec-08cc-4a20-86ce-6e3477abb1c5