我正在创建一个我想从 Java 应用程序使用的 WCF 服务。但问题不在于 .net-java 互操作。
关键点是与服务操作相关的类型之一是 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 架构。Schema 本身很简单,但让我在这里跳过它。
我猜该代码很简单,这是 IXmlSerializable 类型的常见场景。
现在,我们需要 WSDL。我将使用 WSDL 在Metro的帮助下创建 Java 客户端 但实际上 JDK 1.6 就足够了,因为它包含 WS 堆栈(和 wsimport.exe)。所以 java 想要带有 wsdl:service 定义的 wsdl。这就是为什么我不能从 wsdl.exe 给它一个 wsdl(因为 wsdl 生成的 wsdl 不包含 wsdl:service 定义,只有 wsdl:portType)。所以,我调用 wsimport.bat http://localhost/Service1.svc?wsdl
但我得到的是:[ERROR] undefined simple or complex type 'q1:AuxDomainData' line 1 of http://locahost/CustomSerialization/Service1.svc?xsd=xsd3
那是因为组合的 wsdl 实际上不包含 AuxDomainData 之类的类型。这是真的,我们不能责怪 java/metro/任何其他堆栈。如果我们查看由 wcf 生成的 wsdl,它包含 wsdl:types 元素以及所有 xsd 模式的导入:
<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 模式位于http://localhost/CustomSerialization/Service1.svc?xsd=xsd 4 "document" 中。但正如您所见,根 wsdl 不包含对它的引用。那就是问题所在。结果 wsdl/xsd 模式集不完整。
那么,我有哪些选择?