如何避免 SFxCannotImportAsParameters-DifferentWrapperName 错误





0/5 (0投票)
本技巧展示了如何修改 WSDL 文件以避免 SFxCannotImportAsParameters_DifferentWrapperName 异常,该异常在 Visual Studio 中导入 WSDL 文件时抛出。
引言
为了使用 WCF 消费 Web 服务,可以使用 Visual Studio 导入其 WSDL 描述以生成托管客户端。 在提供符合 Visual Studio 要求的 WSDL 描述时,需要考虑一些事项。
本技巧至少展示了如何解决 SFxCannotImportAsParameters_DifferentWrapperName
异常,该异常在生成的代码文件中以以下注释形式表达
"CODEGEN: 生成消息契约,因为指定消息的包装器名称与默认值不匹配。"
背景
解决方案很简单,但我花了半天时间在网上搜索,并且注意到提供的解决方案都无法满足我。 只有通过大量地尝试修改 WSDL 文件,我才找到了解决方案。
解决方案
考虑以下会引发此异常的 WSDL 文档
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:soap-env="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.example.com/services"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.com/services">
<wsdl:message name="TestGetWebserviceVersionRequest"/>
<wsdl:message name="TestGetWebserviceVersionResponse">
<wsdl:part name="result" type="xsd:int"/>
</wsdl:message>
<wsdl:portType name="TestPortType">
<wsdl:operation name="GetWebserviceVersion">
<wsdl:documentation>Get the current webservice version</wsdl:documentation>
<wsdl:input message="tns:TestGetWebserviceVersionRequest"/>
<wsdl:output message="tns:TestGetWebserviceVersionResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="TestBinding" type="tns:TestPortType">
<soap-env:binding xmlns:soap-env="http://schemas.xmlsoap.org/wsdl/soap/" style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="GetWebserviceVersion">
<soap-env:operation soapAction="http://www.hediet.de/projects/enhanced-soap-webservices/code/index.php/service/Test?method=GetWebserviceVersion" style="rpc"/>
<wsdl:input>
<soap-env:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</wsdl:input>
<wsdl:output>
<soap-env:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="Test">
<wsdl:port xmlns:soap-env="http://schemas.xmlsoap.org/wsdl/soap/" name="TestPort" binding="tns:TestBinding">
<soap-env:address xmlns:soap-env="http://schemas.xmlsoap.org/wsdl/soap/" location="http://www.yourwebservice/webservice/test"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
这将让 Visual Studio 生成以下客户端契约(摘录)
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.example.com/services", ConfigurationName="TestWebservice.TestPortType")]
public interface TestPortType {
// CODEGEN: Generating message contract because the wrapper name () of the specified message "GetWebserviceVersionRequest"
// does not match the default value (http://www.example.com/services).
[System.ServiceModel.OperationContractAttribute(
Action="http://www.hediet.de/projects/enhanced-soap-webservices/code/index.php/service/Te" +
"st?method=GetWebserviceVersion", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc,
SupportFaults=true, Use=System.ServiceModel.OperationFormatUse.Encoded)]
ConsoleApplicationSoapTestClient.TestWebservice.GetWebserviceVersionResponse
GetWebserviceVersion(ConsoleApplicationSoapTestClient.TestWebservice.GetWebserviceVersionRequest request);
}
Visual Studio 将参数和结果包装到它们自己的类中:GetWebserviceVersionRequest
和 GetWebserviceVersionResponse
。
可以通过为每个 wsdl:input 元素(//wsdl:portType/wsdl:operation/wsdl:input)指定一个名称来解决该问题,例如“parameters”,以便示例中的 wsdl:portType 元素如下所示
<wsdl:portType name="TestPortType">
<wsdl:operation name="GetWebserviceVersion">
<wsdl:documentation>Get the current webservice version</wsdl:documentation>
<wsdl:input name="parameters" message="tns:TestGetWebserviceVersionRequest"/>
<wsdl:output message="tns:TestGetWebserviceVersionResponse"/>
</wsdl:operation>
</wsdl:portType>
这将让 Visual Studio 生成以下客户端契约(摘录):
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://www.example.com/services", ConfigurationName="TestWebservice.TestPortType")]
public interface TestPortType {
[System.ServiceModel.OperationContractAttribute(Action="http://www.example.com/services/TestPortType/parameters",
ReplyAction="http://www.example.com/services/TestPortType/GetWebserviceVersionResponse")]
[System.ServiceModel.DataContractFormatAttribute(Style=System.ServiceModel.OperationFormatStyle.Rpc)]
[return: System.ServiceModel.MessageParameterAttribute(Name="result")]
int GetWebserviceVersion();
}
现在 GetWebserviceVersion
的签名更易读,并且 CODEGEN 注释消失了。
参考资料
以下链接有所帮助,但没有提供正确的解决方案: