10

I would like to an HTTP header to my WCF SOAP Service. My end goal is to send API keys through this HTTP header.

Below is my code:

[ServiceBehavior(Namespace = "http://****.com/**/1.1")]
public class MyWcfSvc : IMyVerify
{
    const int MaxResponseSize = 0xffff; // 64K max size - Normally it will be MUCH smaller than this

    private static readonly NLogLogger Logger;

    static MyWcfSvc()
    {
        Logger = new NLogLogger();
        // Add an HTTP Header to an outgoing request 
        HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
        requestMessage.Headers["User-Auth"] = "MyHttpHeaderValue";
        OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
    }
}

I do not see User-Auth header under HTTP request headers.

I also tried with another way.

public AnalyzeResponse Analyze(AnalyzeRequest analyzeRequest)
    {
        HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
        requestMessage.Headers["User-Auth"] = "MyHttpHeaderValue";
        OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;
.
.
. Rest of the service implementation
.
.
.
}

But, still, I don't see any HTTP header information with the request message. I am using SOAP UI to send the requests and to view the responses.

How should I go about this? Am I suppose to make changes to the Service related to class? Or I need to make some changes to web.config file?

tRuEsAtM
  • 3,517
  • 6
  • 43
  • 83
  • [How to add a custom HTTP header to every WCF call?](https://stackoverflow.com/questions/964433/how-to-add-a-custom-http-header-to-every-wcf-call) – Ivan Stoev Feb 05 '18 at 20:02
  • I followed that, but it is not working, that's why I asked the question. – tRuEsAtM Feb 06 '18 at 00:56
  • Not sure to understand what you want to accomplish... output an HTTP header in the response when your service sends it, or when someone calls the service, you want to pass and HTTP header, or something else? – mtheriault Feb 06 '18 at 23:42
  • I suggest you include: Server code, Client/consuming code, expected result and actual result (using logs perhaps)... Your question as it stands is confusing. – Leo Feb 08 '18 at 19:04

3 Answers3

10

SOAP Header

To add a SOAP header, use the following code client-side:

using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel))
{
    MessageHeader<string> header = new MessageHeader<string>("MyHttpHeaderValue");
    var untyped = header.GetUntypedHeader("User-Auth", ns);
    OperationContext.Current.OutgoingMessageHeaders.Add(untyped);

    // now make the WCF call within this using block
}

And then, server-side, grab it using:

MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders;
string identity = headers.GetHeader<string>("User-Auth", ns);

NB. ns is The namespace URI of the header XML element.

HTTP Header

To add an Http header:

// Add a HTTP Header to an outgoing request 
HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty();
requestMessage.Headers["MyHttpHeader"] = "MyHttpHeaderValue";
OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage;

And to grab it server-side

IncomingWebRequestContext request = WebOperationContext.Current.IncomingRequest; 
WebHeaderCollection headers = request.Headers; 
Console.WriteLine(request.Method + " " + request.UriTemplateMatch.RequestUri.AbsolutePath); 

foreach (string headerName in headers.AllKeys)
{ 
    Console.WriteLine(headerName + ": " + headers[headerName]); 
}
Leo
  • 5,013
  • 1
  • 28
  • 65
5

If you are trying to add an HTTP request header to the client request, you can follow the procedure below.

Create a client message inspector. For example:

public class CustomInspector : IClientMessageInspector
{
    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        HttpRequestMessageProperty reqProps = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
        if(reqProps == null)
        {
            reqProps = new HttpRequestMessageProperty();
        }

        reqProps.Headers.Add("Custom-Header", "abcd");
        request.Properties[HttpRequestMessageProperty.Name] = reqProps;

        return null;
    }
}

Create an endpoint behavior to load this inspector:

public class CustomBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.ClientMessageInspectors.Add(new CustomInspector());
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

Finally add this behavior to the endpoint.

class Program
{
    static void Main(string[] args)
    {
        ChannelFactory<ICalculator> factory = new ChannelFactory<ICalculator>("BasicHttpsBinding_ICalculator");
        factory.Endpoint.EndpointBehaviors.Add(new CustomBehavior());
        var client = factory.CreateChannel();

        var number = client.Add(1, 2);

        Console.WriteLine(number.ToString());
    }
}

The above example works on my side. I could see the request header with Fiddler.

Chun Liu
  • 903
  • 5
  • 11
3

There is better solution on client-side than Leonardo's. His solution requires to manually modify each request. Here is solution with ClientMessageInspector, which automatically adds header to each outgoing request.

1: Define MessageInspector with overrides: Bellow is the only one override method, the rest is empty.

public class ClientMessageInspector : IClientMessageInspector
{
    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        HttpRequestMessageProperty property = new HttpRequestMessageProperty();
        property.Headers["User-Agent"] = "value";
        request.Properties.Add(HttpRequestMessageProperty.Name, property);
        return null;
    }
...
}
  1. Bind this Message inspector to EndPointBehavior. Bellow is the only one override method, the rest is empty.

    public class CustomEndpointBehavior : IEndpointBehavior
    {
       public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
       {
          clientRuntime.ClientMessageInspectors.Add(new ClientMessageInspector());
       }
       ...
    }
  1. The last step is to add the new behavior to the WCF endpoint:
Endpoint.EndpointBehaviors.Add(new CustomEndpointBehavior());
Leo
  • 5,013
  • 1
  • 28
  • 65
Karel Kral
  • 5,297
  • 6
  • 40
  • 50