WCF Client - How to process or ignore a MustUnderstand header element?

I'm writing a WCF Client that consumes a non-.Net web service, using WS-Security. The service's response contains a Security header with mustUnderstand set to true.

Using a ServiceModelListener, I do see actual data coming back from the service. The WCF client fails, however, because it is not processing the Security header.

<env:Header>
<wsse:Security env:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Timestamp wsu:Id="timestamp">
<wsu:Created>2012-03-28T13:43:54.474Z</wsu:Created>
<wsu:Expires>2012-03-28T13:48:54.474Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</env:Header>

WCF Client Error Message:

The header 'Security' from the namespace 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' was not understood by the recipient of this message, causing the message to not be processed. This error typically indicates that the sender of this message has enabled a communication protocol that the receiver cannot process. Please ensure that the configuration of the client's binding is consistent with the service's binding.

My WCF client doesn't need any of the timestamp info. Is there an easy way to stub in a processing routine? I've already tried extending the Response class & adding a [MessageHeader] property.

EDIT:

Asked another way: How do I implement a WCF client that accepts custom header elements that are marked Must Understand?

There is different standards of WS-Security. Might be it make sense to change the binding at client side, since basicHttpBinding and wsHttpBindings are working with different security standards.

Modify SOAP header Mustunderstand attribute in WCF client, WCF Client - How to process or ignore a MustUnderstand header element? - wcf. Conversely, if a header with the mustUnderstand SOAP header attribute set to true is received by Windows Communication Foundation (WCF), it must be a part of the message contract (or must be processed by one of the Windows Communication Foundation (WCF) channels); otherwise, it is assumed that the header is not understood and an exception is

I ran into a similar issue. I am not sure if this is useful or not.

MSDN WCF Extensibility

http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/19/wcf-extensibility-message-inspectors.aspx

The setup here is Certificate based, Oracle Application Server 10g, and .Net to consume the services. Using SOAPUi was very useful while trying to figure out what was happening with the Request and then the response.

I have not tried modifying the code to use basicHttpBinding, but I used WSHttpBinding as the base of my configuration in code. Then used

 WSHttpBinding binding = new WSHttpBinding()
        {
            CloseTimeout = new TimeSpan(0, 1, 0),
            OpenTimeout = new TimeSpan(0, 1, 0),
            SendTimeout = new TimeSpan(0, 1, 0),
            AllowCookies = false,
            BypassProxyOnLocal = false,
            HostNameComparisonMode = HostNameComparisonMode.StrongWildcard,
            MaxBufferPoolSize = 524288,
            MaxReceivedMessageSize = 65536,
            MessageEncoding = WSMessageEncoding.Text,
            UseDefaultWebProxy = false,
            ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
            {
                MaxDepth = 32,
                MaxArrayLength = 16384,
                MaxBytesPerRead = 4096,
                MaxNameTableCharCount = 16384,
                MaxStringContentLength = 8192
            }
        };
        binding.Security.Mode = SecurityMode.Transport;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
        binding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
        binding.Security.Transport.Realm = string.Empty;
        binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
        binding.Security.Message.EstablishSecurityContext = true;
        binding.Security.Message.NegotiateServiceCredential = true;

        CustomBinding customBinding = new CustomBinding();
        BindingElementCollection collection = binding.CreateBindingElements();

Looped through for the TextMessageEncodingBindingElement to set Soap11 and AddressingVersion to None.

 foreach (BindingElement element in collection)
        {
            if (typeof(TextMessageEncodingBindingElement) == element.GetType())
            {
                TextMessageEncodingBindingElement item = element as TextMessageEncodingBindingElement;
                if (null != item)
                {
                    item.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap11, AddressingVersion.None);
                    customBinding.Elements.Add(item);
                }
            }
            else
                customBinding.Elements.Add(element);
        }

I used the ChannelFactory and added an EndPoint Behavior for a Message Inspector. At this point I then had control of the request and I could add the appropriate header and modified the mustUnderstand on the Action.

Using SOAPUi I took my Message.ToString() and put that in SOAPUI and tested the request. Once the items that were needed were added to the request, it was then determined that the OAS server was not replying with all the necessary elements. Using the message inspector for the reply I modified the message to include the missing headers. I can't remember where I found the base code for the message inspector, but you would need to modify your code to utlize it properly.

For my example here are some snippets.

For the transform message in

 public object BeforeSendRequest

I needed to modify the Header, so using a for loop I grabbed the XElement and added the OASIS header and added a To header.

XNamespace xmlns = "http://schemas.xmlsoap.org/soap/envelope/";
                XElement securityHeader = new XElement(
                    xmlns + "Security", 
                    new XAttribute(xmlns + "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"), 
                    new XAttribute(xmlns + "xmlns", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"), 
                    new XAttribute(xmlns + "mustUnderstand", "0"));
                element.Add(securityHeader);

I also had to modify the Action Header

 else if (localName.Equals("Action", StringComparison.InvariantCultureIgnoreCase))
            {
                foreach (XAttribute a in element.Attributes())
                {
                    if (a.Name.LocalName == "mustUnderstand")
                        a.Value = "0";
                }
            }

My problem was that the Service didn't reply with an Action Header

So in the

 public void AfterReceiveReply

I called my TransformReply returning type Message with something like the following. You may need to modify values for the string.Empty, but this is just an example.

...

 Message reply = Message.CreateMessage(message.Version, null, reader);
        reply.Headers.Add(MessageHeader.CreateHeader("Action", string.Empty, string.Empty, false));
        reply.Properties.CopyProperties(message.Properties);

...

I would really suggest using a tool such as SOUPUI to beable to mess with the envelope and see the reply. If you do SSL, you'll need to create a cacert file and place it in the SSLSettings of the preferences.

Header security error message in WCF client, WCF Client - How to process or ignore a MustUnderstand header element? I'm writing a WCF Client that consumes a non-.Net web service, using WS-Security. You can use an IClientMessageInspector to consume (remove) the header, like in the example below. However, since Action is a well-known header, it's possible that you're using a mismatched binding between the client and server (a message with SOAP 1.2 would have an Action header, while SOAP 1.1 messages don't).

Ran into an issue working on some code around IP cameras supporting ONVIF. Cameras were sending back Nonce and Created in Security element and WCF didn't like it. Ended up using IClientMessageInspector to catch the response, and re-flag the header as mustUnderstand=false.

 public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
    {

        //Some cameras produce WS-Security headers as a repsonse which contain a nonce and created date/time WCF doesn't like this for some reason.
        //The WS-Security element contains mustUnderstand="true". When WCF can't process the unrecoginzed elements it throw an exception. 
        // The code below searches for a WS-Security header. If one is found it copies the message body and all headers but the WS-Security header.
        // A new WS-Security header is then created with mustUnderstand=false and added into the new message. The proxy clients
        // will still receive the WS-Security header, just won't throw exceptions because of Nonce and Created elements in the header.
        if (reply.Headers.Count > 0)
        {
            //Have a WS-Security header?
            int secHeaderIndex = reply.Headers.FindHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
            if (secHeaderIndex < 0) { return; }

            //Our replacement message
            System.ServiceModel.Channels.Message cleanedMessage = null;
            //Copy the body
            cleanedMessage = Message.CreateMessage(reply.Version, "", reply.GetReaderAtBodyContents());
            //Create a new WS-Security header with mustUnmderstand=false
            MessageHeader newSecHeader = MessageHeader.CreateHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", reply.Headers[0], false);
            for (int x=0; x<reply.Headers.Count; x++)
            {
                if (x == secHeaderIndex)
                {//Don't copy the old WS-Security header
                    continue;
                }
                //Not a WS-Security header, copy to the new message.
                cleanedMessage.Headers.CopyHeaderFrom(reply, x);
            }
            cleanedMessage.Headers.Add(newSecHeader);
            reply = cleanedMessage;
        }
    }

"mustUnderstand"-attribute in WCF client - MSDN, Hi All, I get an error message when invoking a WCF operation using a . -client- how-to-process-or-ignore-a-mustunderstand-header-element. The SoapUI has the Must-Understand set to None, therefore I would not expect the service to implement the Must-understand header element . What is interesting is that when I host the same service locally the client is able to invoke it with no issues.

WCF requests - added header element *To* - MSDN, using the following configuration, I'm trying to build a WCF-client for a address header and/or to set the "mustUnderstand" attribute for those headers? appear to be best handled by taking over some aspect of the process in code. I guess it's because of the <a:Action>-element (which is added by the´┐Ż true if the XML Web service must properly interpret and process the SoapHeader; otherwise, false. The default is false. Examples. The following XML Web service client defines a custom SOAP header of type MyHeader, sets the MustUnderstand property to true, and invokes the MyWebMethod XML Web service method.

WCF Client - How to process or ignore a MustUnders, In order for wcf client to send SOAP.12 message without the soap protocol allows a server to ignore a header if must understand=0), you might just and the client can specify which nodes need to process your message. In WCF, custom channels never generate mustUnderstand faults. Instead, the WCF Dispatcher, which is located at the top of the WCF communication stack, checks to see that all headers that were marked as MustUnderstand=true were understood by the underlying stack. If any were not understood, a mustUnderstand fault is generated at that point.

Suppressing mustUnderstand validation on unknown SoapHeaders , The WCF client fails, however, because it is not processing the that accepts custom header elements that are marked Must Understand? SOAP Headers with Published WCF Services. 06/08/2017; 2 minutes to read; In this article. The WCF receive adapters can copy all the SOAP header values in the inbound messages to the InboundHeaders property, or they can write or promote specified values to the BizTalk message context.

Comments
  • Thanks, but the service supports only basicHttpBinding.
  • Thanks Adam! looks like interesting info. I've moved on to a different consulting engagement now though, so can no longer try things out against that system. Fyi, previously client ultimately solved the issue via a different architectural approach.