I'm just trying to get started with WCF. It seems like it's super simple, but using a simple API like SOAP :: Lite, I'm having trouble working. There are many dated examples in googlesphere, and I tried many of them to no avail. So now I am trying to break the problem to the lowest level. I created a WCF application created by the Visual Web Developer 2008 Express template. This is his service contract:
[ServiceContract] public interface IService1 { [OperationContract] string GetData(int value); [OperationContract] CompositeType GetDataUsingDataContract(CompositeType composite);
I started it in debug mode and tried to establish contact. Doing this using a browser using the debug url http://localhost:59315/Service1.svc gives me a page that says the following:
You have created a service.
To test this service, you need to create a client and use it to call the service. You can do this using the svcutil.exe tool from the command line with the following syntax:
svcutil.exe http://localhost:59315/Service1.svc?wsdl
So then I go to this wsdl and get the following:
<wsdl:definitions name="Service1" targetNamespace="http://tempuri.org/"> <wsp:Policy wsu:Id="WSHttpBinding_IService1_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SymmetricBinding> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:RequireDerivedKeys/> <sp:BootstrapPolicy> <wsp:Policy> <sp:SignedParts> <sp:Body/> <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> <sp:SymmetricBinding> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:SpnegoContextToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:RequireDerivedKeys/> </wsp:Policy> </sp:SpnegoContextToken> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> <sp:EncryptSignature/> <sp:OnlySignEntireHeadersAndBody/> </wsp:Policy> </sp:SymmetricBinding> <sp:Wss11> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefIssuerSerial/> <sp:MustSupportRefThumbprint/> <sp:MustSupportRefEncryptedKey/> </wsp:Policy> </sp:Wss11> <sp:Trust10> <wsp:Policy> <sp:MustSupportIssuedTokens/> <sp:RequireClientEntropy/> <sp:RequireServerEntropy/> </wsp:Policy> </sp:Trust10> </wsp:Policy> </sp:BootstrapPolicy> </wsp:Policy> </sp:SecureConversationToken> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> <sp:EncryptSignature/> <sp:OnlySignEntireHeadersAndBody/> </wsp:Policy> </sp:SymmetricBinding> <sp:Wss11> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefIssuerSerial/> <sp:MustSupportRefThumbprint/> <sp:MustSupportRefEncryptedKey/> </wsp:Policy> </sp:Wss11> <sp:Trust10> <wsp:Policy> <sp:MustSupportIssuedTokens/> <sp:RequireClientEntropy/> <sp:RequireServerEntropy/> </wsp:Policy> </sp:Trust10> <wsaw:UsingAddressing/> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy wsu:Id="WSHttpBinding_IService1_GetData_Input_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SignedParts> <sp:Body/> <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy wsu:Id="WSHttpBinding_IService1_GetData_output_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SignedParts> <sp:Body/> <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy wsu:Id="WSHttpBinding_IService1_GetDataUsingDataContract_Input_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SignedParts> <sp:Body/> <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsp:Policy wsu:Id="WSHttpBinding_IService1_GetDataUsingDataContract_output_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SignedParts> <sp:Body/> <sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/> <sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts> <sp:EncryptedParts> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy> <wsdl:types> <xsd:schema targetNamespace="http://tempuri.org/Imports"> <xsd:import schemaLocation="http://localhost:59315/Service1.svc?xsd=xsd0" namespace="http://tempuri.org/"/> <xsd:import schemaLocation="http://localhost:59315/Service1.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/> <xsd:import schemaLocation="http://localhost:59315/Service1.svc?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/RossDominosService"/> </xsd:schema> </wsdl:types> <wsdl:message name="IService1_GetData_InputMessage"> <wsdl:part name="parameters" element="tns:GetData"/> </wsdl:message> <wsdl:message name="IService1_GetData_OutputMessage"> <wsdl:part name="parameters" element="tns:GetDataResponse"/> </wsdl:message> <wsdl:message name="IService1_GetDataUsingDataContract_InputMessage"> <wsdl:part name="parameters" element="tns:GetDataUsingDataContract"/> </wsdl:message> <wsdl:message name="IService1_GetDataUsingDataContract_OutputMessage"> <wsdl:part name="parameters" element="tns:GetDataUsingDataContractResponse"/> </wsdl:message> <wsdl:portType name="IService1"> <wsdl:operation name="GetData"> <wsdl:input wsaw:Action="http://tempuri.org/IService1/GetData" message="tns:IService1_GetData_InputMessage"/> <wsdl:output wsaw:Action="http://tempuri.org/IService1/GetDataResponse" message="tns:IService1_GetData_OutputMessage"/> </wsdl:operation> <wsdl:operation name="GetDataUsingDataContract"> <wsdl:input wsaw:Action="http://tempuri.org/IService1/GetDataUsingDataContract" message="tns:IService1_GetDataUsingDataContract_InputMessage"/> <wsdl:output wsaw:Action="http://tempuri.org/IService1/GetDataUsingDataContractResponse" message="tns:IService1_GetDataUsingDataContract_OutputMessage"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="WSHttpBinding_IService1" type="tns:IService1"> <wsp:PolicyReference URI="#WSHttpBinding_IService1_policy"/> <soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="GetData"> <soap12:operation soapAction="http://tempuri.org/IService1/GetData" style="document"/> <wsdl:input> <wsp:PolicyReference URI="#WSHttpBinding_IService1_GetData_Input_policy"/> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <wsp:PolicyReference URI="#WSHttpBinding_IService1_GetData_output_policy"/> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="GetDataUsingDataContract"> <soap12:operation soapAction="http://tempuri.org/IService1/GetDataUsingDataContract" style="document"/> <wsdl:input> <wsp:PolicyReference URI="#WSHttpBinding_IService1_GetDataUsingDataContract_Input_policy"/> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <wsp:PolicyReference URI="#WSHttpBinding_IService1_GetDataUsingDataContract_output_policy"/> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="Service1"> <wsdl:port name="WSHttpBinding_IService1" binding="tns:WSHttpBinding_IService1"> <soap12:address location="http://localhost:59315/Service1.svc"/> <wsa10:EndpointReference> <wsa10:Address>http://localhost:59315/Service1.svc</wsa10:Address> <Identity> <Dns>localhost</Dns> </Identity> </wsa10:EndpointReference> </wsdl:port> </wsdl:service> </wsdl:definitions>
Nothing too crazy (except for SOAP itself) ... Anyway, now I will try a simple SOAP :: Lite application:
#!/cygdrive/C/Perl64/bin/perl.exe -w use strict; use warnings; use Data::Dumper; use SOAP::Lite +trace => [ transport => sub { my ($in) = @_; if ( ref($in) eq "HTTP::Request") { print( "REQUEST\n" . $in->content() . "\nEND REQUEST\n" ); } elsif ( ref($in) eq "HTTP::Response") { print( "RESPONSE\n" . $in->content() . "\nEND RESPONSE\n" ); } } ]; my $server = 'http://localhost:59315/Service1.svc'; my $url = "$server?wsdl"; my $xmlns = 'http://schemas.datacontract.org/2004/07/RossDominosService';
Which of the debugging issues this SOAP request:
<?xml version="1.0" encoding="UTF-8"?> <soap:Envelope xmlns:namesp1="http://localhost:59315/Service1.svc?wsdl" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <namesp1:GetData> <value xsi:type="xsd:int">5</value> </namesp1:GetData> </soap:Body> </soap:Envelope>
But the answer is returned with:
failed: ************************** 415 Unsupported Media Type *****************************
What's happening? This is "Hello world!" SOAP applications, and I can't figure it out.
----------------------- UPDATE -------------------- ------ -----
I found that I need to change the default wsHttpBinding to:
<endpoint address="" binding="basicHttpBinding" contract="RossDominosService.IService1">
Now it connects, but I get this new error:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <s:Fault> <faultcode xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none">a:ActionNotSupported</faultcode> <faultstring xml:lang="en-US">The message with Action 'http://tempuri.org/GetData' 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, eg Message, Transport, None).</faultstring> </s:Fault> </s:Body> </s:Envelope>
It doesn't seem like it was that hard ...
----------------------- UPDATE -------------------- ------ -----
Got! After some additional intervention and some help from soapUI, I found out that the action needs to be changed so that it:
<namespace>/<serviceContract>/<method>
in this case:
http:
When using SOAP :: Lite SOAPAction by default
<namespace>
So you should change your soap object like this:
$soap->on_action( sub { sprintf( '%sIService1/%s', @_ ) } );
I will write the answer below so that we can close this question ...