none
Sending custom HTTP header RRS feed

  • Question

  • Hello,

    I am trying to test calling a Java web service from C# console application.  Since the requirement is to use client side certificate, I use wsHttpBinding.

    I have to pass a custom HTTP header (ClientId) as part of this call.  I tried using OperationContextScope class like below -

    try
    {
    using ( eventClient ec = new eventClient())
    
    using (OperationContextScope scope = new OperationContextScope(ec.InnerChannel)) 
    {
      MessageHeader header = MessageHeader.CreateHeader("ClientId", "<VALUE>", "value");
                            OperationContext.Current.OutgoingMessageHeaders.Add(header);
    .....
    }
                         

    But the above didn't work.

    So my question is - how to pass a custom HTTP header to this web service?  Any info would be greatly appreciated.

    • Moved by Bob Shen Wednesday, May 8, 2013 6:15 AM
    Tuesday, May 7, 2013 3:26 PM

All replies

  • The WCF, Serialsiation and Networking Forum might be a better place to ask:

    http://social.msdn.microsoft.com/Forums/en-US/wcf/threads

    But I have to wonder why you are using HTT Protocoll to cumminicate with something that is likely not returning a HTML page? There are bound to be better way to cummunicate, and my first target would be a XML-based Protocol.


    Let's talk about MVVM: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2

    Tuesday, May 7, 2013 5:08 PM
  • Hi,

    To add a custom header to the outgoing message, you can create a class that implements IClientMessageInspector, add the header in the BeforeSendRequest method, then create an endpoint behavior that applies the message inspector to the client runtime.

    http://stackoverflow.com/questions/964433/how-to-add-a-custom-header-to-every-wcf-calls

    #Adding HTTP Headers to WCF Calls

    http://blogs.msdn.com/b/mohamedg/archive/2012/12/13/adding-http-headers-to-wcf-calls.aspx

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, May 8, 2013 7:50 AM
    Moderator
  • Hi Haixia,

    Thanks for your help.

    I have implemented class extending IClientMessageInspector as below -

        public class ClientMessageInspector : IClientMessageInspector
        {
            public object BeforeSendRequest(ref Message request, IClientChannel channel)
            {
                HttpRequestMessageProperty property = new HttpRequestMessageProperty();
    
                property.Headers["ClientId"] = "<VAL>";
                request.Properties.Add(HttpRequestMessageProperty.Name, property);
    
                return null;
            }
    
            public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
                // Nothing 
            }
    
            public class BindingBehavior : IEndpointBehavior
            {
                public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
                    //ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
                {
                    clientRuntime.MessageInspectors.Add(new ClientMessageInspector());
                }
    
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
                {
                    // Nothing 
                }
    
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                    // Nothing             }
    
                public void Validate(ServiceEndpoint endpoint)
                {
                    // Nothing
                }
            }
        }
    

    But struggling to bind my app.config to the above implementation i.e. the above class extending IClientMessageInspector doesn't get called.  My app.config below -

      <system.serviceModel>
        <bindings>
                <wsHttpBinding>
                    <binding name="AccountStatus.EventType.event"  maxReceivedMessageSize="4194304" maxBufferPoolSize="2147483647" 
                             messageEncoding="Text" textEncoding="Utf-8">
                      <security mode="Transport">
                        <transport clientCredentialType="Certificate" proxyCredentialType="None" realm="" />
                        <message clientCredentialType="Certificate" negotiateServiceCredential="false"
                                 establishSecurityContext="false" algorithmSuite="Default" />
                      </security>
                    </binding>
                </wsHttpBinding>
            </bindings>    
        <client>
          <endpoint address="https://<SERVICE>"  
                    behaviorConfiguration="BindingBehavior"
            binding="wsHttpBinding"
            bindingConfiguration="AccountStatus.EventType.event"
            contract="EventType.event"
            name="servicegateway" />
        </client>
        <behaviors>
          <serviceBehaviors>
            <behavior name="BindingBehavior">
              <serviceMetadata httpsGetEnabled="true" httpsGetUrl=""/>
              <serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="BindingBehavior">
              <clientCredentials>
                <clientCertificate findValue="<CLIENT CERT VAL>"                               storeLocation="CurrentUser"                                x509FindType="FindByThumbprint" />
              </clientCredentials>
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <extensions>
          <behaviorExtensions>
            <add name="BindingBehavior"
                type="System.ServiceModel.ClientMessageInspector, Namespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5dd6890f6ea002e5"/>
          </behaviorExtensions>
        </extensions>
      </system.serviceModel>
    

    Can you let me know how to resolve this issue please?

    Thanks in advance,

    Thursday, May 9, 2013 10:48 AM
  • Hi,

    When register the extension with configuration, the type is the yournamespace.BindingBehavior you have defined but not the 'ClientMessageInspector' as showed in the configuration you posted above. Here is an example for your information.

    #Creating Custom WCF Endpoint Behavior

    http://burcakcakiroglu.com/?p=2083

    Best Regards.


    Haixia
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, May 10, 2013 8:24 AM
    Moderator
  • Hi Haixia,

    Many thanks for your help so far.

    I tried as per the link you mentioned.  But during compile I get a warning and then when I try to run, a run time error.  Warning and error messages are below -

    Warning	
    The element 'behavior' has invalid child element 'DefaultEndpointBehavior'. List of possible elements expected: 'clientVia, callbackDebug, callbackTimeouts, clear, clientCredentials, transactedBatching, dataContractSerializer, dispatcherSynchronization, remove, synchronousReceive, enableWebScript, webHttp, endpointDiscovery, soapProcessing'.


    Error
    The type 'Namespace.ServiceCultureBehavior, Namespace' registered for extension 'DefaultEndpointBehavior' could not be loaded.


    The code behind the class and app.config are below.  As I am novice in .NET development, any help would be greatly appreciated.

    Class extending IClientMessageInspector below -

    namespace Namespace
    {
        public class ServiceCultureMessageInspector : IClientMessageInspector
        {
            private const string HeaderKey = "ClientId";
    
            public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
            {
                Console.WriteLine("BeforeSendReply called");
    
                request.Headers.Add(MessageHeader.CreateHeader(HeaderKey, string.Empty, "<VALUE>"));
    
                return null;
            }
    
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                return null;
            }
    
            public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
            }
    
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
            }
        }
    
    
        public class ServiceCultureBehavior : BehaviorExtensionElement, IEndpointBehavior
        {
            public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
            {
                clientRuntime.MessageInspectors.Add(new ServiceCultureMessageInspector());
            }
    
            public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
            }
    
            protected override object CreateBehavior()
            {
                return new ServiceCultureBehavior();
            }
    
            public void Validate(ServiceEndpoint endpoint)
            {
            }
    
            public override System.Type BehaviorType
            {
                get { return typeof(ServiceCultureBehavior); }
            }
        }
    }


    app.config below -

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <extensions>
          <behaviorExtensions>
            <add name="DefaultEndpointBehavior"
                type="Namespace.ServiceCultureBehavior, Namespace" />
          </behaviorExtensions>
        </extensions>
        <behaviors>
          <endpointBehaviors>
            <behavior name="DefaultEndpointBehavior">
              <DefaultEndpointBehavior/>
              <clientCredentials>
                <clientCertificate findValue=" <VALUE>"
                                   storeLocation="CurrentUser"
                                   x509FindType="FindByThumbprint" />
              </clientCredentials>
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
              <endpointDiscovery enabled="true" />         
            </behavior>
          </endpointBehaviors>
        </behaviors>
        <bindings>
                <wsHttpBinding>
                    <binding name="AccountStatus.EventType.event"  maxReceivedMessageSize="4194304" maxBufferPoolSize="2147483647" 
                             messageEncoding="Text" textEncoding="Utf-8" >
                      <security mode="Transport">
                        <transport clientCredentialType="Certificate" proxyCredentialType="None" realm="" />
                        <message clientCredentialType="Certificate" negotiateServiceCredential="false"
                                 establishSecurityContext="false" algorithmSuite="Default" />
                      </security>
                    </binding>
                </wsHttpBinding>
        </bindings>
        <client>
          <endpoint address="https://<JAVA ENDPOINT>"
                  binding="wsHttpBinding"
                  contract="EventType.event"
                  behaviorConfiguration="DefaultEndpointBehavior"
                  bindingConfiguration="AccountStatus.EventType.event"
            name="servicegateway" />
        </client>
      </system.serviceModel>
    </configuration>


    Thanks,


    Friday, May 10, 2013 4:00 PM
  • Hey, the DefaultEndpointBehavior seems unexpected, also the namespace(it depend on the project you created) is not right in your scenario, try make changes for your application from the error message visual studio give.

    <behavior name="DefaultEndpointBehavior">
             
    <DefaultEndpointBehavior/>
             
    <clientCredentials>

    Monday, May 13, 2013 9:57 AM
  • Hello Nico_He,

    Thanks for your time.

    As can be seen from my code above -

    * namespace is just 'Namespace' and
    * the class extending 'BehaviorExtensionElement' is 'ServiceCultureBehavior'.

    Therefore in my app.config, I have written the behavior extensions as below -

    <behaviorExtensions>
            <add name="DefaultEndpointBehavior"
                type="Namespace.ServiceCultureBehavior, Namespace" />
          </behaviorExtensions>

    And tried to refer the above from Behavior as below -

    <behaviors>
          <endpointBehaviors>
            <behavior name="DefaultEndpointBehavior">
              <DefaultEndpointBehavior/>
              <clientCredentials>
                <clientCertificate findValue=" <VALUE>"
                                   storeLocation="CurrentUser"
                                   x509FindType="FindByThumbprint" />
              </clientCredentials>
              <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
              <endpointDiscovery enabled="true" />         
            </behavior>
          </endpointBehaviors>
        </behaviors>

    But still get the warning and error mentioned in my above post. What could be wrong here?

    Alternatively, is there any alternative to app.config option i.e. can I call the class extended from 'BehaviorExtensionElement' directly by code?

    Any info would be greatly appreciated.

    Monday, May 13, 2013 10:26 AM