We're trying to access a webservice (which I believe is also coded using WCF, but I have no control over it whatsoever) and I get an exception:
System.ServiceModel.FaultException: WSE012: The input was not a valid SOAP message because the following information is missing: action.
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(
ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action,
Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs,
TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(
IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(
IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(
MessageData& msgData, Int32 type)
at ClientName.ProjectName.Services.ServiceName.ServiceNameSoap.CallServiceName(
Request request)
at ClientName.ProjectName.Scheduler.ThirdPartyName.ProcessServiceName.Execute(
Object state) in ...\ProcessServiceName.cs:line 65
The calling code in ProcessServiceName.Execute
reads:
Request serviceRequest = request.BuildServiceRequest();
Result result = client.CallServiceName(serviceRequest);
LogServiceErrors(db, request.ServiceNameRequestId, result.errors);
and the exception is coming from the second of those lines, which calls directly into the WCF code autogenerated by the Service Reference, calling System.ServiceModel.ClientBase<T>. Channel
.CallServiceName(request)
; the method BuildServiceRequest
just takes the database object and converts it to the object required by the webservice.
The relevant part of the App.config
(this is called within a Windows Service) reads:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webBinding">
</binding>
</webHttpBinding>
<wsHttpBinding>
<binding name="ThirdPartySoap" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00"
sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false"
hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288"
maxReceivedMessageSize="65536" messageEncoding="Text"
textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192"
maxArrayLength="16384" maxBytesPerRead="4096"
maxNameTableCharCount="16384"/>
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None"
realm="www.serviceprovider.com"/>
<message clientCredentialType="UserName"
algorithmSuite="Default"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint name="ServiceNameSoap"
address="https://www.serviceprovider.com/ServiceName.asmx"
binding="wsHttpBinding" bindingConfiguration="ThirdPartySoap"
contract="ServiceName.ServiceNameSoap"/>
</client>
</system.serviceModel>
Given that all the code that does the actual webservice work is from within WCF, I don't quite understand what the problem is but, presumably, I need something slightly different in my App.config
to prevent it.
Having looked on Google, I'm finding nothing of any help. On StackOverflow, this unanswered WCF question from September 2011 is of no help; custom bindings (answer from November 2009 and link about WSE) don't help (and I barely understand them), and both a forum answer from November 2009 and a ColdFusion thing from October 2009 are unrelated. All the other Google hits I'm seeing are duplicates of these links.
Any assistance would be greatly appreciated!
Wiktor Zychla has rightly pointed out that the problem could (theoretically) be in the proxy classes. However, these classes are wholly unedited from the classes generated automatically; for example:
using System.CodeDom.Compiler;
using System.ServiceModel;
using System.ServiceModel.Channels;
namespace ClientName.ProjectName.Services.ServiceName
{
[GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface ServiceNameSoapChannel : ServiceNameSoap, IClientChannel {}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class ServiceNameSoapClient : ClientBase<ServiceNameSoap>,
ServiceNameSoap
{
public ServiceNameSoapClient() { }
public ServiceNameSoapClient(string endpointConfigurationName) :
base(endpointConfigurationName) { }
public ServiceNameSoapClient(string endpointConfigurationName,
string remoteAddress) :
base(endpointConfigurationName, remoteAddress) { }
public ServiceNameSoapClient(string endpointConfigurationName,
EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) { }
public ServiceNameSoapClient(Binding binding,
EndpointAddress remoteAddress) : base(binding, remoteAddress) { }
public Result CallServiceName(Request request)
{ return base.Channel.CallServiceName(request); }
}
}
All the other proxy classes are similarly unedited from the autogenerated code (which I've edited here for whitespace and namespace optimisation, so that it fits better on screen within StackOverflow; the three namespaces I've added using
statements for were fully-qualified on all class references, as was the namespace I've redacted to ClientName.ProjectName.Services.ServiceName
in these samples.
Having added WCF Message Logging, I get the following in my message log. (This is from a different service call than the code above, but throwing the same exception, partly because this service call is simpler, partly because not all service calls are being logged, for some reason. The only edit I have made is to make the error message legible without horizontal scrolling.)
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2013-01-18T12:00:04.7166250Z" />
<Source Name="System.ServiceModel.MessageLogging" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="ClientName.ProjectName.Scheduler" ProcessID="8600" ThreadID="10" />
<Channel/>
<Computer>MachineNameRedacted</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<MessageLogTraceRecord Time="2013-01-18T12:00:04.7166250+00:00" Source="TransportSend" Type="System.ServiceModel.Dispatcher.OperationFormatter+OperationFormatterMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.serviceprovider.com/RedactedActionName</a:Action>
<a:MessageID>urn:uuid:395d6394-5f4b-4954-8df0-8fb82d17072a</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://www.serviceprovider.com/ServiceName.asmx</a:To>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<RedactedActionName xmlns="http://www.serviceprovider.com">
<brandId>2</brandId>
</RedactedActionName>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
</E2ETraceEvent>
<E2ETraceEvent xmlns="http://schemas.microsoft.com/2004/06/E2ETraceEvent">
<System xmlns="http://schemas.microsoft.com/2004/06/windows/eventlog/system">
<EventID>0</EventID>
<Type>3</Type>
<SubType Name="Information">0</SubType>
<Level>8</Level>
<TimeCreated SystemTime="2013-01-18T12:00:04.7635000Z" />
<Source Name="System.ServiceModel.MessageLogging" />
<Correlation ActivityID="{00000000-0000-0000-0000-000000000000}" />
<Execution ProcessName="ClientName.ProjectName.Scheduler" ProcessID="8600" ThreadID="10" />
<Channel/>
<Computer>MachineNameRedacted</Computer>
</System>
<ApplicationData>
<TraceData>
<DataItem>
<MessageLogTraceRecord Time="2013-01-18T12:00:04.7635000+00:00" Source="TransportReceive" Type="System.ServiceModel.Channels.BufferedMessage" xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
<env:Header xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<wsa:Action>http://schemas.xmlsoap.org/ws/2004/08/addressing/fault</wsa:Action>
<wsa:MessageID>urn:uuid:b72c6f30-8409-4b55-8c79-056d82f990a5</wsa:MessageID>
<wsa:To>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
</env:Header>
<soap:Body>
<soap:Fault>
<soap:Code>
<soap:Value>soap:Sender</soap:Value>
</soap:Code>
<soap:Reason>
<soap:Text xml:lang="en">
WSE012: The input was not a valid SOAP message because
the following information is missing: action.
</soap:Text>
</soap:Reason>
</soap:Fault>
</soap:Body>
</soap:Envelope>
</MessageLogTraceRecord>
</DataItem>
</TraceData>
</ApplicationData>
As Wiktor Zychla has requested, here is the ServiceNameSoap
interface declaration, from the autogenerated code, again edited only to fit better on screen (hence the using
) and to redact the the client-confidential names:
using System.ServiceModel;
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel","4.0.0.0")]
[ServiceContractAttribute(Namespace="https://www.serviceprovider.com/",
ConfigurationName="ServiceName.ServiceNameSoap")]
public interface ServiceNameSoap
{
[OperationContractAttribute(
Action="https://www.serviceprovider.com/ServiceName",
ReplyAction="*")]
[XmlSerializerFormatAttribute(SupportFaults=true)]
[ServiceKnownTypeAttribute(typeof(ClientRequest))]
[return: MessageParameterAttribute(Name="result")]
ClientName.ProjectName.Services.ServiceName.Result CallServiceName(
ClientName.ProjectName.Services.ServiceName.Request request);
}
(joint effort with the OP)
I've just saw that your service is exposed on an .asmx endpoint which suggests that this is not a wcf service but rather an old asp.net service. Asp.net web services in contrary to wcf have very limited configuration options, they do not support ws/web binding (only basic http). My advice then is to switch to an old type proxy, generate it with wsdl.exe tool. You don't need any configuration and you can't use the wsHttpBinding but at least you should be able to call the service.