none
SOAP Action override at runtime from imported WSDL

    Question

  • I have imported a WSDL (that I have no control over) and I need the ability to override the SOAPAction during runtime.  The import prototype ends up looking something like this:

     

    Public Interface System_PortType

    <System.ServiceModel.OperationContractAttribute(Action:="Config", ReplyAction:="*"), _

    System.ServiceModel.XmlSerializerFormatAttribute()> _

     

    Function Config(ByVal request As Parameters) As Config

     

    End Interface

    It appears that the message create derives it's SOAPAction from the "Action:" option listed in the definition, but I need to override that SOAPAction depending on runtime information (a few arguments need to be added.)  How can I get access to read/write that information at runtime?  (I'm using VB, but any examples would be helpful.)

    Thanks!

    Wednesday, June 30, 2010 9:50 PM

Answers

  • Hi,

    You can modify the action header by Message Inspector:

     

      class MyEndpointBehavior : IEndpointBehavior
        {
            #region IEndpointBehavior Members

            public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
            {
                
            }

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

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

            public void Validate(ServiceEndpoint endpoint)
            {
              
            }

            #endregion
        }
        class MyInspector : IClientMessageInspector
        {
            #region IClientMessageInspector Members

            public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
              
            }

            public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
            {
                request.Headers.Action = "http://actionmodified";
                return null;
            }

            #endregion
        }
        class Program
        {
            static void Main(string[] args)
            {
                ServiceReference1.Service1Client proxy = new Client.ServiceReference1.Service1Client();
                proxy.Endpoint.Behaviors.Add(new MyEndpointBehavior());
                  
                    Console.WriteLine(proxy.GetData(1));
                    Console.ReadLine();
        
            }
        }


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Windows Azure Platform China Blog: http://blogs.msdn.com/azchina/default.aspx
    • Marked as answer by Dan Slacker Wednesday, July 07, 2010 10:43 PM
    Friday, July 02, 2010 8:36 AM
    Moderator

All replies

  • Hello Dan,

    if you mean SOAPAction HTTP header you can check this thread: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/2c68ea86-3555-4d1e-9cda-ff1e8d17d480/?prof=required Unfortunatelly I haven't found the way to modify SOAPAction header manually. WCF handles it internally based on provided values from WSDL and I am sure it is correct behavior. Your service breaks interoperability when it requires other SOAPAction than defined in WSDL - sorry to say it but that is the reson why you have the problem.

    Best regards,
    Ladislav

    Wednesday, June 30, 2010 10:17 PM
  • Thanks for your quick response.  I'm not sure I completely agree that the problem is the fault of the service (or WSDL generated from it).  According to the specification that you pointed out in another thread:

    "The SOAPAction HTTP request header field can be used to indicate the intent of the SOAP HTTP request. The value is a URI identifying the intent. SOAP places no restrictions on the format or specificity of the URI or that it is resolvable."

    So, that is really the only restriction.  What Microsoft (and a lot of developers) assume, is that when you consume a service that you will always be connecting to that same service.  In this case, the SOAPAction can be used by a service developer to provide identifying information.  Let's assume that this developer uses the SOAPAction to pass a variable piece of data to change it's intent (which would allow different customers to deploy this service without modification but implement it in different ways - this is a completely valid case).  Now, when consuming this service, you WILL need to change the information in SOAPAction, which is not something the seems easy to do using WCF.

    Unless I missed a piece of the specification, this seems like a valid scenario that's just not supported - or am I completely off base here?

     

    Thanks ... Dan

    Thursday, July 01, 2010 12:08 AM
  • Hi,

    You can modify the action header by Message Inspector:

     

      class MyEndpointBehavior : IEndpointBehavior
        {
            #region IEndpointBehavior Members

            public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
            {
                
            }

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

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

            public void Validate(ServiceEndpoint endpoint)
            {
              
            }

            #endregion
        }
        class MyInspector : IClientMessageInspector
        {
            #region IClientMessageInspector Members

            public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
            {
              
            }

            public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
            {
                request.Headers.Action = "http://actionmodified";
                return null;
            }

            #endregion
        }
        class Program
        {
            static void Main(string[] args)
            {
                ServiceReference1.Service1Client proxy = new Client.ServiceReference1.Service1Client();
                proxy.Endpoint.Behaviors.Add(new MyEndpointBehavior());
                  
                    Console.WriteLine(proxy.GetData(1));
                    Console.ReadLine();
        
            }
        }


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. Windows Azure Platform China Blog: http://blogs.msdn.com/azchina/default.aspx
    • Marked as answer by Dan Slacker Wednesday, July 07, 2010 10:43 PM
    Friday, July 02, 2010 8:36 AM
    Moderator