Spyne与Core WCF处理多复杂类型参数的差异验证及W3C标准合规性确认
Great question! Let's break down your questions and fix the interoperability issue step by step.
1. Is your understanding correct?
Absolutely. Your core observation is spot-on:
- Spyne generates a named
<xs:complexType>(name="Delivery") to wrap the operation's parameters, then references this type from a top-level<xs:element>also namedDelivery. - Core WCF defines an anonymous
<xs:complexType>directly inside the top-level<xs:element name="Delivery">, with no standalonenameattribute for the type.
This difference creates a mismatch in SOAP request structure: Spyne expects parameters to be nested inside an extra wrapper node matching the named complex type, while your third-party app sends requests formatted to match WCF's anonymous structure—leading to the failed calls you're seeing.
2. Which implementation follows the W3C standard?
Both are compliant! The W3C SOAP/WSDL specifications don't mandate whether parameter containers must use named or anonymous complex types—both patterns are valid. The problem here is a framework convention mismatch:
- Spyne defaults to a "wrapped" style with named parameter types.
- Core WCF uses its own default wrapping convention that produces anonymous complex types.
This is purely an interoperability issue between different SOAP framework implementations, not a violation of the W3C standard.
Fixing the Spyne Service to Match WCF's Structure
To make your Spyne service compatible with the third-party app, you need to adjust two key parts of your code:
a. Use _body_style='bare' for RPC Methods
Spyne's @rpc decorator supports the _body_style parameter. Setting it to 'bare' disables the default named parameter wrapping, generating an anonymous complex type structure matching WCF's output.
b. Correct Parameter Names and Logic
Your original code had a typo (parameter named item instead of items, matching the C# interface) and a broken loop. Fix these to ensure proper handling of the input data.
Corrected Spyne Code
from spyne import ( Application, rpc, ServiceBase, Iterable, Integer, Unicode, ComplexModel, ) from spyne.protocol.soap import Soap11 from spyne.server.wsgi import WsgiApplication import logging logging.getLogger().setLevel(logging.INFO) class Info(ComplexModel): Id = Integer Name = Unicode class Item(ComplexModel): Id = Integer Name = Unicode Value = Unicode class Callback(ServiceBase): # Enable bare body style to match WCF's parameter structure @rpc(Info, Iterable(Item), _body_style='bare') def Delivery(ctx, info, items): logging.info(f">>>> Info - {info}") for item in items: logging.info(f">>>>>>>> item - {item}") # Apply bare style to TestCallback for consistency @rpc(Unicode, _returns=Unicode, _body_style='bare') def TestCallback(ctx, data): logging.info(f">>>> Test - {data}") return data application = Application( [Callback], "http://tempuri.org/", # Match WCF's default namespace (critical for interoperability) in_protocol=Soap11(validator="lxml"), out_protocol=Soap11(), ) wsgi_application = WsgiApplication(application)
Additional Note: Namespace Matching
WCF defaults to using http://tempuri.org/ as the service namespace. Your original Spyne code used spyne.examples.hello.soap, which would also cause mismatches. Make sure to set the Spyne application's namespace to match the one used by the third-party WCF service.
After making these changes, your Spyne service will generate WSDL that mirrors Core WCF's structure, allowing the third-party app to call your SOAP callback service successfully.
内容的提问来源于stack exchange,提问作者Isham Mohamed

