How to add a custom HTTP header to every WCF call?

后端 未结 13 2415
不知归路
不知归路 2020-11-22 05:33

I have a WCF service that is hosted in a Windows Service. Clients that using this service must pass an identifier every time they\'re calling service methods (because that i

13条回答
  •  攒了一身酷
    2020-11-22 06:21

    If you want to add custom HTTP headers to every WCF call in an object oriented way, look no further.

    Just as in Mark Good's and paulwhit's answer, we need to subclass IClientMessageInspector to inject the custom HTTP headers into the WCF request. However, lets make the inspector more generic by accepting an dictionary containing the headers we want to add:

    public class HttpHeaderMessageInspector : IClientMessageInspector
    {
        private Dictionary Headers;
    
        public HttpHeaderMessageInspector(Dictionary headers)
        {
            Headers = headers;
        }
    
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            // ensure the request header collection exists
            if (request.Properties.Count == 0 || request.Properties[HttpRequestMessageProperty.Name] == null)
            {
                request.Properties.Add(HttpRequestMessageProperty.Name, new HttpRequestMessageProperty());
            }
    
            // get the request header collection from the request
            var HeadersCollection = ((HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]).Headers;
    
            // add our headers
            foreach (var header in Headers) HeadersCollection[header.Key] = header.Value;
    
            return null;
        }
    
        // ... other unused interface methods removed for brevity ...
    }
    

    Just as in Mark Good's and paulwhit's answer, we need to subclass IEndpointBehavior to inject our HttpHeaderMessageInspector into our WCF client.

    public class AddHttpHeaderMessageEndpointBehavior : IEndpointBehavior
    {
        private IClientMessageInspector HttpHeaderMessageInspector;
    
        public AddHttpHeaderMessageEndpointBehavior(Dictionary headers)
        {
            HttpHeaderMessageInspector = new HttpHeaderMessageInspector(headers);
        }
    
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.ClientMessageInspectors.Add(HttpHeaderMessageInspector);
        }
    
        // ... other unused interface methods removed for brevity ...
    }
    

    The last part needed to finish our object oriented approach, is to create a subclass of our WCF auto-generated client (I used Microsoft's WCF Web Service Reference Guide to generate a WCF client).

    In my case, I need to attach an API key to the x-api-key HTML header.

    The subclass does the following:

    • calls the constructor of the base class with the required parameters (in my case a EndpointConfiguration enum was generated to pass into the constructor - maybe your implementation won't have this)
    • Defines the headers that should be attached to every requests
    • Attaches AddHttpHeaderMessageEndpointBehavior to the client's Endpoint behaviors
    public class Client : MySoapClient
    {
        public Client(string apiKey) : base(EndpointConfiguration.SomeConfiguration)
        {
            var headers = new Dictionary
            {
                ["x-api-key"] = apiKey
            };
    
            var behaviour = new AddHttpHeaderMessageEndpointBehavior(headers);
            Endpoint.EndpointBehaviors.Add(behaviour);
        }
    }
    

    Finally, use your client!

    var apiKey = 'XXXXXXXXXXXXXXXXXXXXXXXXX';
    var client = new Client (apiKey);
    var result = client.SomeRequest()
    

    The resulting HTTP request should contain your HTTP headers and look something like this:

    POST http://localhost:8888/api/soap HTTP/1.1
    Cache-Control: no-cache, max-age=0
    Connection: Keep-Alive
    Content-Type: text/xml; charset=utf-8
    Accept-Encoding: gzip, deflate
    x-api-key: XXXXXXXXXXXXXXXXXXXXXXXXX
    SOAPAction: "http://localhost:8888/api/ISoapService/SomeRequest"
    Content-Length: 144
    Host: localhost:8888
    
    
      
        
      
    
    

提交回复
热议问题