Adding a custom SoapHeader via Contract
The SOAP message (used by an XML Web Service and WCF service) is a standard XML document consisting of a root Envelope
tag, which in turn consists of a required Body
element and an optional Header
element. Each sub element under the optional Header
is called a SoapHeader
, which plays a similar role as the other headers, uses a certain network protocol's transmit package.
A SoapHeader is often used in SOAP messages to carry some application protocol-level data in addition to the SOAP body. WCF has used many built-in SoapHeaders for certain protocols it supports (WS-Security, WS-Reliability, and so on). For some user scenarios, we will also need to add a custom SoapHeader into the WCF service message so as to exchange additional information (mostly for communication purposes).
How to do it...
We need to define a custom type, which represents the SoapHeader that will be serialized in the service message. Here is a sample
DataContract
type that represents a custom header used for custom authentication:[DataContract] public class MyUsernameToken { [DataMember] public string Username { get; set; } [DataMember] public string Password { get; set; } }
Next, we can apply the custom
Header
type into our service operation'sMessageContract
. What we should do here is mark theMessageContract
member (of theHeader
type) withMessageHeaderAttribute
.[MessageContract] public class HelloRequest { [MessageHeader] public MyUsernameToken AuthUser { get; set; } [MessageBodyMember] public string User { get; set; } } [MessageContract] public class HelloResponse { [MessageBodyMember] public string Reply { get; set; } }
At the end, we need to use the
MessageContract
type as the only input parameter/return value of the particular service operation.
How it works...
The MessageHeaderAttribute helps mark the particular type member (of MessageContract
type) as the SoapHeader that will be embedded in the resulting SOAP Envelope. Also, since the header is added in MessageContract
at design-time, the WCF auto-generated metadata will include the SoapHeader information, as shown in the following screenshot:
If you use Visual Studio or Svcutil.exe to generate the client proxy class, the generated proxy type will automatically map the SoapHeaders to operation parameters. Thus, when invoking the service operation, we can simply pass SoapHeader data as the operation parameter. The following code demonstrates how the auto-generated service proxy invokes the operation with the custom SoapHeader assigned.
private static void CallService() { TestProxy.TestServiceClient client = new TestProxy.TestServiceClient(); TestProxy.MyUsernameToken utoken = new TestProxy.MyUsernameToken{ Username="Foo", Password="Bar"}; string reply = client.SayHello(utoken, "WCF user"); Console.WriteLine(reply); }
By capturing the underlying SOAP message, we can find that the MyUsernameToken
header type is serialized as a SoapHeader within the <Header>
section.
There's more...
WCF supports various means to add custom SoapHeader a into service messages. This recipe demonstrates using a custom type and MessageContract
to add a custom SoapHeader statically. In addition to this, we can also use code to programmatically add SoapHeaders into service messages.
See also
Using MessageContract to control the SOAP message
Adding a dynamic SoapHeader into a message in Chapter 5
Securing a dynamic SoapHeader in Chapter 7
Complete source code for this recipe can be found in the
\Chapter 1\recipe6\
folder