WSE012: The input was not a valid SOAP message because the following information is missing: action

StackOverflow https://stackoverflow.com/questions/14381667

  •  16-01-2022
  •  | 
  •  

Pregunta

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!


Edit to add more detail

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>

Even more detail: ServiceNameSoap interface

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);
}
¿Fue útil?

Solución 2

We have a winner…

Wiktor's comments led me to look at Interop between WCF and WSE3.0, and try using MessageVersion.Soap12WSAddressingAugust2004 in a CustomBinding by overriding Binding.CreateBindingElements so that the method ClientName.ProjectName.Services. ServiceName.ServiceNameSoapClient.CallServiceName changed from:

public Result CallServiceName(Request request)
{
    return base.Channel.CallServiceName(request);
}

(as in the original question) to:

using System.ServiceModel.Channels;

public Result CallTestDrive(Request request)
{
    BindingElementCollection elements
        = base.Endpoint.Binding.CreateBindingElements();
    elements.Find<MessageEncodingBindingElement>().MessageVersion
        = MessageVersion.Soap12WSAddressingAugust2004;
    base.Endpoint.Binding = new CustomBinding(elements);

    return base.Channel.CallTestDrive(request);
}

(code adapted from Modifying the Binding of a Service on Nicholas Allen's WCF blog).

This would seem to have solved my problem. At last.

Thank you very much Wiktor and John Saunders; I wouldn't have got to this without your assistance.


Edit: Another failed attempt below

Again for completeness's sake, I shall include another avenue I tried that did not work for me. I also tried following the instructions from this answer to the question WCF CustomBinding Configuration, creating a Custom Binding class in my namespace ClientName.ProjectName.ServiceName:

using System.ServiceModel;
using System.ServiceModel.Channels;

public class CustomWsHttpBinding : WSHttpBinding
{
    public override BindingElementCollection CreateBindingElements()
    {
        BindingElementCollection elements = base.CreateBindingElements();

        MessageEncodingBindingElement encodingElement
          = elements.Find<MessageEncodingBindingElement>();
        encodingElement.MessageVersion
          = MessageVersion.Soap12WSAddressingAugust2004;

        return elements;
    }
}

and adding it to the config with:

<system.serviceModel>
    <extensions>
        <bindingExtensions>
            <add name="CustomWsHttpBinding"
             type="ClientName.ProjectName.ServiceName.CustomWsHttpBinding, ClientName.ProjectName.ServiceName" />
        </bindingExtensions>
    </extensions>
    <bindings>
        <CustomWsHttpBinding>
            <binding name="ServiceNameSoap" 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>
        </CustomWsHttpBinding>
    </bindings>
    <!-- ... -->
</system.serviceModel>

Otros consejos

(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.

I know this is 2 years old but i figured i'd give the simplest solution. I may be rehashing the above answer. The trick is to realize that old school asmx services we pre ws-* acceptance. There are 2 versions(maybe more) of the WS-Addressing feature - August 2005 and the problematic August 2004. You can see these in SOAPUI where you have to manually change the WS-A version to "200408" when testing .asmx services. All that does is essentially change the ws-addressing header from:

<soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">

to

<soap:Header xmlns:wsa="http://www.w3.org/2004/08/addressing">

so the question is, how would you do this in WCF? Simply, as the above stated is to NOT use wsHttpBinding but to use custom binding and setting the message version. Without further Adieu, the relevent WebConfig:

<system.serviceModel> <client> <endpoint address="http://localhost/some_old_school_garbage_service/adapterws.asmx" binding="customBinding" bindingConfiguration="AdapterWSSoap" contract="AdapterWS.AdapterWSSoap" name="LodestarASMX" /> </client> <bindings> <customBinding> <binding name="AdapterWSSoap" > <security authenticationMode="UserNameOverTransport" allowInsecureTransport="True"></security> <textMessageEncoding messageVersion="Soap12WSAddressingAugust2004"></textMessageEncoding> <httpTransport/> </binding> </customBinding>

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top