How can I deserialize a custom SOAP header in WCF?

I am trying to add a custom header for all SOAP requests through WCF. I found this fantastic article on how to do this. My MessageHeader class is as follows:

 public class OperatorNameMessageHeader : MessageHeader { private string opName; public const string HeaderName = "OperatorNameMessageHeader"; public const string HeaderNamespace = "http://schemas.microsoft.com/scout"; public override string Name { get { return HeaderName; } } public override string Namespace { get { return HeaderNamespace; } } public string OperatorName { get { return opName; } set { opName = value; } } public OperatorNameMessageHeader() { } public OperatorNameMessageHeader(string operatorName) { opName = operatorName; } protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) { writer.WriteElementString("OperatorName", opName); } } 

One article does not say how to read the value on the server. According to this post, you can use OperationContext.Current.IncomingMessageHeaders to read these headers. When I look at these MessageHeaders under the debugger, I see 3 headers, including my own. Thus, it is definitely mapped to SOAP data. However, when I call GetHeader :

 OperatorNameMessageHeader test = msgHeaders.GetHeader<OperatorNameMessageHeader>(OperatorNameMessageHeader.HeaderName, OperatorNameMessageHeader.HeaderNamespace); 

Then test.OperatorName is null. Basically, I just return an empty OperatorNameMessageHeader object that has not been deserialized from the data in SOAP.

My next step was to start the WCF tracer. When I do this, I can verify that the custom header is indeed sent through the wire:

 <MessageHeaders> <ActivityId CorrelationId="66a7c5b6-3548-4f3c-9120-4484af76b64b" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">f9bef03b-4e7b-4e84-b327-5e79814d9933</ActivityId> <OperatorNameMessageHeader xmlns="http://schemas.microsoft.com/scout"> <OperatorName>Correct Operator Name</OperatorName> </OperatorNameMessageHeader> <To d4p1:mustUnderstand="1" xmlns:d4p1="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:90/IRolesAndResourcesManager</To> <Action d4p1:mustUnderstand="1" xmlns:d4p1="http://schemas.xmlsoap.org/soap/envelope/" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IRolesAndResourcesManager/Authenticate</Action> </MessageHeaders> 

So, the server has data, I just can’t get to it. What is the solution to this problem?

+5
source share
1 answer

I had a similar problem. I have to read the annd password username from the headers. I found a workaround, I am using XmlDictionaryReader. But with this code I am only looking for names, I can still improve it, but it works at the moment. I have it for VB, there will be something similar for C #

  Dim username As String = "" Dim password As String = "" Dim usernameTokenId As String = "" Dim passwordType As String = "" For i As Integer = 0 To OperationContext.Current.IncomingMessageHeaders.Count - 1 Dim mhi As Channels.MessageHeaderInfo = OperationContext.Current.IncomingMessageHeaders.Item(i) Dim headers As Channels.MessageHeaders = OperationContext.Current.RequestContext.RequestMessage.Headers If mhi.Name.Equals("Security") Then Dim xr As XmlDictionaryReader = OperationContext.Current.IncomingMessageHeaders.GetReaderAtHeader(i) xr.MoveToContent() While xr.MoveToNextAttribute() Console.Write(" {0}='{1}'", xr.Name, xr.Value) End While Do Select Case xr.NodeType Case XmlNodeType.Element If xr.LocalName.Equals("Username") Then username = xr.ReadElementContentAsString() End If If xr.LocalName.Equals("Password") Then password = xr.ReadElementContentAsString() End If While xr.MoveToNextAttribute() If xr.LocalName.Equals("Id") Then usernameTokenId = xr.Value End If If xr.LocalName.Equals("Type") Then passwordType = xr.Value End If End While Case XmlNodeType.Attribute 'Case XmlNodeType.Text ' Console.Write(xr.Value) 'Case XmlNodeType.EndElement ' Console.Write("</{0}>", xr.Name) End Select Loop While xr.Read() End If Dim name As String = mhi.Name Next 
0
source

Source: https://habr.com/ru/post/1200692/


All Articles