如何将 "catch-all" xsd:any 元素注入到 WSDL 描述的每个响应对象中?
How to inject "catch-all" xsd:any element into every response object described by a WSDL?
我们有一个由 C# 和 Java 客户端使用的 SOAP Web 服务。
问题在于,当我们升级 Web 服务时,客户端并不急于重新生成代理,因此为旧版本生成的代理代码可能会被用于使用较新版本的服务。
碰巧,向响应对象添加新的 属性 会破坏使用已生成的旧代理代码的 Java 客户端。显然,Java 在其对 WSDL 的解释上非常严格,并且当 属性 到达时 WSDL 中不存在的异常失败。至少,这是我们观察到的由 apache 轴生成的代理代码。 C# 客户端很好 - 新属性被简单地忽略了。
我正在想办法解决这个问题。一种似乎可行的解决方案是将 xsd:any
属性 注入到 WSDL 中找到的每个响应对象中。据我了解,各种 Java 实现将把它用作所有未知属性的 "catch-all" 属性 (当然,客户将不得不重新生成他们的代理来使用这些 xsd:any 定义,但一旦完成,新的属性将抓住并破坏它们的代码)
问题是我如何才能在 WSDL 中注入这些 xsd:any
属性,而不实际向响应对象添加真正的 "catch-all" 属性?
我们的 Web 服务是使用 WCF 实现的。
显然,实现它的唯一方法是引入一个新的端点行为,该行为也实现了 IWsdlExportExtension
接口。那么,我们开始吧:
public class WSDLFilterBehavior : IWsdlExportExtension, IEndpointBehavior
{
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
// never called
}
public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
{
var schemas = exporter.GeneratedXmlSchemas.Schemas(@"http://Abc/Services/Data");
foreach (XmlSchema schema in schemas)
{
for (int i = schema.Items.Count - 1; i >= 0; --i)
{
// Do some other processing ...
var schemaComplexType = schema.Items[i] as XmlSchemaComplexType;
if (schemaComplexType == null)
{
continue;
}
XmlSchemaSequence xmlSchemaSequence;
var xmlSchemaContentModel = schemaComplexType.ContentModel;
if (xmlSchemaContentModel == null)
{
if (schemaType.Name.StartsWith("ArrayOf"))
{
continue;
}
xmlSchemaSequence = schemaComplexType.Particle as XmlSchemaSequence;
}
else
{
var xmlSchemaComplexContentExtension = xmlSchemaContentModel.Content as XmlSchemaComplexContentExtension;
if (xmlSchemaComplexContentExtension == null)
{
continue;
}
xmlSchemaSequence = xmlSchemaComplexContentExtension.Particle as XmlSchemaSequence;
}
if (xmlSchemaSequence == null)
{
continue;
}
var xmlSchemaObject = new XmlSchemaAny
{
MinOccurs = 0
};
xmlSchemaSequence.Items.Add(xmlSchemaObject);
}
}
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
// not needed
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
// not needed
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,EndpointDispatcher dispatcher)
{
// not needed
}
public void Validate(ServiceEndpoint endpoint)
{
// not needed
}
}
它起作用了,它在所有元素中注入 xs:any
(不是 xsd:any
,但我想它是相同的),除了那些不是从任何其他类型派生并开始的元素"ArrayOf".
我们有一个由 C# 和 Java 客户端使用的 SOAP Web 服务。
问题在于,当我们升级 Web 服务时,客户端并不急于重新生成代理,因此为旧版本生成的代理代码可能会被用于使用较新版本的服务。
碰巧,向响应对象添加新的 属性 会破坏使用已生成的旧代理代码的 Java 客户端。显然,Java 在其对 WSDL 的解释上非常严格,并且当 属性 到达时 WSDL 中不存在的异常失败。至少,这是我们观察到的由 apache 轴生成的代理代码。 C# 客户端很好 - 新属性被简单地忽略了。
我正在想办法解决这个问题。一种似乎可行的解决方案是将 xsd:any
属性 注入到 WSDL 中找到的每个响应对象中。据我了解,各种 Java 实现将把它用作所有未知属性的 "catch-all" 属性 (当然,客户将不得不重新生成他们的代理来使用这些 xsd:any 定义,但一旦完成,新的属性将抓住并破坏它们的代码)
问题是我如何才能在 WSDL 中注入这些 xsd:any
属性,而不实际向响应对象添加真正的 "catch-all" 属性?
我们的 Web 服务是使用 WCF 实现的。
显然,实现它的唯一方法是引入一个新的端点行为,该行为也实现了 IWsdlExportExtension
接口。那么,我们开始吧:
public class WSDLFilterBehavior : IWsdlExportExtension, IEndpointBehavior
{
public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
{
// never called
}
public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
{
var schemas = exporter.GeneratedXmlSchemas.Schemas(@"http://Abc/Services/Data");
foreach (XmlSchema schema in schemas)
{
for (int i = schema.Items.Count - 1; i >= 0; --i)
{
// Do some other processing ...
var schemaComplexType = schema.Items[i] as XmlSchemaComplexType;
if (schemaComplexType == null)
{
continue;
}
XmlSchemaSequence xmlSchemaSequence;
var xmlSchemaContentModel = schemaComplexType.ContentModel;
if (xmlSchemaContentModel == null)
{
if (schemaType.Name.StartsWith("ArrayOf"))
{
continue;
}
xmlSchemaSequence = schemaComplexType.Particle as XmlSchemaSequence;
}
else
{
var xmlSchemaComplexContentExtension = xmlSchemaContentModel.Content as XmlSchemaComplexContentExtension;
if (xmlSchemaComplexContentExtension == null)
{
continue;
}
xmlSchemaSequence = xmlSchemaComplexContentExtension.Particle as XmlSchemaSequence;
}
if (xmlSchemaSequence == null)
{
continue;
}
var xmlSchemaObject = new XmlSchemaAny
{
MinOccurs = 0
};
xmlSchemaSequence.Items.Add(xmlSchemaObject);
}
}
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
// not needed
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
// not needed
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,EndpointDispatcher dispatcher)
{
// not needed
}
public void Validate(ServiceEndpoint endpoint)
{
// not needed
}
}
它起作用了,它在所有元素中注入 xs:any
(不是 xsd:any
,但我想它是相同的),除了那些不是从任何其他类型派生并开始的元素"ArrayOf".