Suppressing mustUnderstand validation on unknown SoapHeaders

For a WCF service or client proxy, it is common to receive SoapHeaders within the coming request or returned response messages. SoapHeader has a mustUnderstand attribute that indicates to the target endpoint (or intermediate message processor) whether the SoapHeader must be processed. The following screenshot shows a typical SOAP message that contains a SoapHeader with the mustUnderstand attribute set to 1 (true).

Suppressing mustUnderstand validation on unknown SoapHeaders

Also for a XML Web Service or WCF service, we can dynamically insert SoapHeaders at runtime or statically apply them at design-time (which will be described via WSDL or service metadata).

By default, a WCF endpoint will perform validation on all the SoapHeaders within incoming messages, and if there are any unknown SoapHeaders (not predefined) which have a mustUnderstand attribute as 1 (or true), a validation exception will be raised by the runtime. However, sometimes it is useful to suppress this validation so that the WCF service or client proxy can gracefully handle unknown SoapHeaders that are dynamically added.

Getting ready

If you are not familiar with SoapHeaders and the mustUnderstand attribute, or how to set this attribute via the WCF programming model, you can take a look at the following references first:

How to do it...

By injecting MustUnderstandBehavior into our WCF endpoint’s behavior collection, we can suppress the validation and raising of exceptions on unknown SoapHeaders with mustUnderstand=”1”. The steps are as follows:

  1. First, we need to create a MustUnderstandBehavior type instance and set its ValidateMustUnderstand property to false (which can be done in the type constructor).
  2. Second, we should locate the service/client endpoint instance on which we want to apply MustUnderstandBehavior. For the WCF service, we can use ServiceHost.Description.Endpoints collection to find the wanted endpoint. For the client proxy, we can directly use [ClientProxy].Endpoint to get the endpoint instance.
  3. After we get the endpoint instance, we can simply add the MustUnderstandBehavior instance into the endpoint instance’s Behaviors collection.

    The following code shows the complete steps for applying MustUnderstandBehavior in service hosting code:

    using (ServiceHost host = new ServiceHost(typeof(HeaderTestService)))
    {
       // Suppress the MustUnderstand header’s validation so that exception won’t be raised for unknown MustUnderstand headers              
     MustUnderstandBehavior mubehavior = new MustUnderstandBehavior(false);
       // Find the target endpoint we want
     ServiceEndpoint endpoint = host.Description.Endpoints.Find(typeof(IHeaderTestService));
       // Add the MustUnderstandBehavior to our service endpoint’s Behavior collection              
     endpoint.Behaviors.Add(mubehavior);
    
    }
    

How it works...

When you encounter the ProtocolException (as shown in the next screenshot), it is probably because the WCF service or client endpoint received an unknown SoapHeader that is marked as mustUnderstand=true.

How it works...

After applying MustUnderstandBehavior (with ValidateMustUnderstand set to false), the runtime will ignore validation on any unknown SoapHeaders. But, we can still use code to access them from OperationContext, as follows:

StringBuilder sb = new StringBuilder();
sb.AppendFormat(“{0} headers in message\n”, OperationContext.Current.IncomingMessageHeaders.Count);
foreach (var header in OperationContext.Current.IncomingMessageHeaders)
{
    sb.AppendFormat(“HeaderName:{0}, MustUnderstand={1}\n”, header.Name, header.MustUnderstand);
}

There’s more...

In this recipe, we demonstrated how to inject the MustUnderstandBehavior for a self-hosting scenario. However, in many cases, our WCF service will be hosted on IIS server via .svc endpoints. In such cases, we can use a custom ServiceHostFactory class to add the behavior injecting code logic. You can have a look at the article Extending Hosting Using ServiceHostFactory at http://msdn.microsoft.com/en-us/library/aa702697.aspx.

See also

  • Customizing IIS ServiceHost via ServiceHostFactory in Chapter 3
  • Complete source code for this recipe can be found in the \Chapter 2\recipe7\ folder