0

I'm trying to add this Header class to my SOAP request but can't see how. The Header class was given to me as part of the implementation but there's no instructions on how to use it and I'm a bit stuck - I've not used WSDL and web services before. I'm sure the answer must be blindingly easy but I just can't see it.

Header Requirements

<soapenv:Header>
  <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
    <wsse:UsernameToken wsu:Id="UsernameToken-19" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
      <wsse:Username>##USERNAME##</wsse:Username>
      <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">##PASSWORD##</wsse:Password>
     </wsse:UsernameToken>
  </wsse:Security>
</soapenv:Header>   

Header class

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.Web;
using System.Xml;
using System.Xml.Serialization;

namespace Consuming
{
    public class SecurityHeader : MessageHeader
    {
        private readonly UsernameToken _usernameToken;

        public SecurityHeader(string id, string username, string password)
        {
            _usernameToken = new UsernameToken(id, username, password);
        }

        public override string Name
        {
            get { return "Security"; }
        }

        public override string Namespace
        {
            get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
        }

        protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(UsernameToken));
            serializer.Serialize(writer, _usernameToken);
        }
    }


    [XmlRoot(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
    public class UsernameToken
    {
        public UsernameToken()
        {
        }

        public UsernameToken(string id, string username, string password)
        {
            Id = id;
            Username = username;
            Password = new Password() { Value = password };
        }

        [XmlAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")]
        public string Id { get; set; }

        [XmlElement]
        public string Username { get; set; }

        [XmlElement]
        public Password Password { get; set; }
    }

    public class Password
    {
        public Password()
        {
            Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
        }

        [XmlAttribute]
        public string Type { get; set; }

        [XmlText]
        public string Value { get; set; }
    }
}

Code

var mySoapHeader = new SecurityHeader("ID","Username","password");
var client = new GroupWebServiceClient(); // Created from Add Web Reference

client.?????? = mySoapHeader;// I can't see how to add the Header to the request

var response = new groupNameListV1(); 
response = client.getAllDescendants("6335");//This needs the header - omitting gives "An error was discovered processing the <wsse:Security> header"

EDIT

I figured it out in the end, turns out it was pretty easy - Adding the solution in case anyone else finds it useful

using (new OperationContextScope(client.InnerChannel))
    {
         OperationContext.Current.OutgoingMessageHeaders.Add(
                    new SecurityHeader("ID", "USER", "PWD"));

         var response = new groupNameListV1();
         response = client.getAllDescendants("cng_so_6553");
         //other code
    }
DrDan
  • 63
  • 5

1 Answers1

0

Generally you need to add behavior extension.

Create a class that implements IClientMessageInspector. In the BeforeSendRequest method, add your custom header to the outgoing message. It might look something like this:

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request,  System.ServiceModel.IClientChannel channel)
{
HttpRequestMessageProperty httpRequestMessage;
object httpRequestMessageObject;
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject))
{
    httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty;
    if (string.IsNullOrEmpty(httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER]))
    {
        httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER] = this.m_userAgent;
    }
}
else
{
    httpRequestMessage = new HttpRequestMessageProperty();
    httpRequestMessage.Headers.Add(USER_AGENT_HTTP_HEADER, this.m_userAgent);
    request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage);
}
return null;
}

Then create an endpoint behavior that applies the message inspector to the client runtime. You can apply the behavior via an attribute or via configuration using a behavior extension element.

Here is a example of how to add an HTTP user-agent header to all request messages. I used this in a few of my clients.

Is this what you had in mind?

Bartosz Kowalczyk
  • 1,479
  • 2
  • 18
  • 34