我正在学习 WCF,特别是我正在学习如何首先编写合同,ala wscf.blue
我可以按最后一种方式创建 WCF 客户端/服务合同(Microsoft) 我可以按第一种方式创建 WCF 客户端/服务合同(WSCF)
但是,如果我创建一个合同优先服务,然后尝试以 Microsoft 方式(服务参考)而不是 WSCF.blue 方式(共享合同并生成客户端)添加它,它不起作用。
它抛出一个ActionNotSupportedException
带有消息的The message with Action 'urn:test-com:simple:testMethodIn' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
我不知道这意味着什么。
这是我的测试合同:
简单模型.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="urn:test-com:simple" xmlns:mstns="urn:test-com:simple" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:test-com:simple" elementFormDefault="qualified" attributeFormDefault="unqualified" id="SimpleModel">
<xs:complexType name="PayloadType">
<xs:sequence>
<xs:element name="AString" type="xs:string" nillable="1" minOccurs="0"/>
<xs:element name="AnInt" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
简单消息.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns="urn:test-com:simple" xmlns:mstns="urn:test-com:simple" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:smod="http://tempuri.org/SimpleModel.xsd" targetNamespace="urn:test-com:simple" elementFormDefault="qualified" attributeFormDefault="unqualified" id="SimpleMessages">
<xs:include schemaLocation="SimpleModel.xsd"/>
<xs:element name="TestMethod">
<xs:complexType>
<xs:sequence>
<xs:element name="APayload" type="PayloadType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="TestMethodResponse">
<xs:complexType>
<xs:sequence>
<xs:element name="Output" type="PayloadType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
简单的.wsdl
<!--WSDL generated by thinktecture WSCF; version 1.0.13.0-->
<!--Tuesday, 09-10-2012 - 02:41 PM-->
<definitions xmlns:tns="urn:test-com:simple" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" name="Simple" targetNamespace="urn:test-com:simple">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>
<types>
<xsd:schema>
<xsd:import schemaLocation="SimpleMessages.xsd" namespace="urn:test-com:simple"/>
</xsd:schema>
</types>
<message name="testMethodIn">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>
<part name="parameters" element="tns:TestMethod"/>
</message>
<message name="testMethodOut">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>
<part name="parameters" element="tns:TestMethodResponse"/>
</message>
<portType name="SimpleInterface">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>
<operation name="TestMethod">
<wsdl:documentation xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"/>
<input message="tns:testMethodIn"/>
<output message="tns:testMethodOut"/>
</operation>
</portType>
<binding name="BasicHttpBinding_SimpleInterface" type="tns:SimpleInterface">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="TestMethod">
<soap:operation soapAction="urn:test-com:simple:testMethodIn" style="document"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="ISimple">
<port name="NewPort" binding="tns:BasicHttpBinding_SimpleInterface">
<soap:address location="http://localhost:50862/Simple.svc"/>
</port>
</service>
</definitions>
这是 web.config 中的 system.serviceModel 部分
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="SimpleServiceBehaviour">
<serviceMetadata externalMetadataLocation="http://localhost:50862/TestContract/Simple.wsdl" httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<diagnostics>
<messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true"/>
</diagnostics>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_SimpleInterface" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="SimpleServiceBehaviour" name="SimpleContract.Simple">
<endpoint address="http://localhost:50862/Simple.svc" behaviorConfiguration="" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SimpleInterface" contract="ISimple"/>
</service>
</services>
</system.serviceModel>
如果我添加对 Every 的服务引用http://localhost:50862/Simple.svc
似乎会生成 OK。
我通过导入 web.config 使用服务配置编辑器在客户端 app.config 中创建它:
<system.serviceModel>
<client>
<endpoint address="http://localhost:50862/Simple.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SimpleInterface" contract="SI.SimpleInterface" name="NewPort"/>
</client>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_SimpleInterface" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/>
<security mode="None">
<transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
<message clientCredentialType="UserName" algorithmSuite="Default"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
如果我运行我的测试代码:
static void Main(string[] args)
{
SimpleInterfaceClient client = new SimpleInterfaceClient();
var ret = client.TestMethod(new PayloadType() { AnInt = 7, AString = "bob" });
Console.WriteLine(ret.ToString());
Console.ReadLine();
}
在 TestMethod 代理内部,以下行:
return base.Channel.TestMethod(request);
抛出以下异常
System.ServiceModel.ActionNotSupportedException occurred
Message="The message with Action 'urn:test-com:simple:testMethodIn' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)."
Source="System.ServiceModel"
StackTrace:
at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
有人可以帮忙吗?
谢谢,
J。
第一次编辑
好的,我现在发现我的 doc-lit-wrapped wsdl 和代码生成器出了点问题。wscf.blue 不喜欢将可空类型标记为可空的消息。它脱离了包装模式,并且方法实现没有被解包。
但是,如果我不将它们标记为可空,则客户端代码将退出包装模式,因为它们是可空类型,未标记为可空。
将可空类型标记为不可空:
服务器端:
[System.ServiceModel.OperationContractAttribute(Action="urn:test-com:simple/ISimple/TestMethod", ReplyAction="urn:test-com:simple/ISimple/TestMethodResponse")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[return: System.ServiceModel.MessageParameterAttribute(Name="Output")]
PayloadType TestMethod(PayloadType APayload);
客户端:
// CODEGEN: Generating message contract since element name APayload from namespace urn:test-com:simple is not marked nillable
[System.ServiceModel.OperationContractAttribute(Action="urn:test-com:simple:testMethodIn", ReplyAction="*")]
DesktopClientTest_ServiceReference.SI.TestMethodResponse TestMethod(DesktopClientTest_ServiceReference.SI.TestMethodRequest request);
将可空类型标记为可空:
服务器端:
// CODEGEN: Parameter 'Output' requires additional schema information that cannot be captured using the parameter mode. The specific attribute is 'System.Xml.Serialization.XmlElementAttribute'.
[System.ServiceModel.OperationContractAttribute(Action="urn:test-com:simple/ISimple/TestMethod", ReplyAction="urn:test-com:simple/ISimple/TestMethodResponse")]
[System.ServiceModel.XmlSerializerFormatAttribute(SupportFaults=true)]
[return: System.ServiceModel.MessageParameterAttribute(Name="Output")]
TestMethodResponse TestMethod(TestMethodRequest request);
客户端:
[System.ServiceModel.OperationContractAttribute(Action="urn:test-com:simple:testMethodIn", ReplyAction="*")]
[return: System.ServiceModel.MessageParameterAttribute(Name="Output")]
DesktopClientTest_ServiceReference.SI.PayloadType TestMethod(DesktopClientTest_ServiceReference.SI.PayloadType APayload);
但是我不知道这是否是原因,更不用说如何解决它了。也就是说,我确实知道对于 doc-lit-wrapped wsdl 应该将可空类型标记为可空类型。