none
ClientMessageInspector initiated, but BeforeSendRequest not called RRS feed

  • Question

  • This has struggled my head for a few days now. I have an Endpoint behavior and Client Message inspector like example code below, and I cant get the BeforeSendRequest to be called. In debugging I have logged activity and I see proof of the messageInspector constructor been initiated, but I do not see the appropriate method beeing called. The behavior is beeing used in an .net 3.5 environment. Do anyone see an obvious problem in the code, or have I missed something else? The behavoir is registered in machine.config and used in an BizTalk environment. I do not get any errors, only see that the code is not run.

     

    BehaviorExtensionElement

    public class CustomBehaviorElement : BehaviorExtensionElement
        {
            ConfigurationProperty("Var1", IsRequired = true, DefaultValue = "")]
            public string Var1
            {
                get { return (string)base["Var1"]; }
                set { base["Var1"] = value; }
            }
    
            [ConfigurationProperty("Var2", IsRequired = true, DefaultValue = "")]
            public string Var2
            {
                get { return (string)base["Var2"]; }
                set { base["Var2"] = value; }
            }
            
            protected override object CreateBehavior()
            {
                return new CustomBehavior(Var1, Var2);
            }
    
            public override Type BehaviorType
            {
                get { return typeof(CustomBehavior); }
            }
        }
    }

    EndpointBehavior

    public class CustomBehavior : IEndpointBehavior
    
        {
            private readonly string _var1;
            private readonly string _var2;
    
            public CustomBehavior(string var1, string var2)
            {
                _var1 = var1;
                _var2 = var2;
            }
            
            public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                //logging
    
                var inspector = new CustomMessageInspector(_var1, _var2);
                clientRuntime.MessageInspectors.Add(inspector);
    
                //logging
          }
    
            public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
                //DoNothing
            }
    
            public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
            {
                //DoNothing
            }
            
            public void Validate(ServiceEndpoint endpoint)
            {
                //DoNothing
            }
        }

    ClientMessageInspector

    public class CustomMessageInspector : IClientMessageInspector
        {
            private readonly string _var1;
            private readonly string _var2;
    
            public CustomMessageInspector(string var1, string var2)
            {
                //Logging
    
                _var1 = var1;
                _var2 = var2;
            }
            
            public object BeforeSendRequest(ref Message request, IClientChannel channel)
            {
                //Logging (THIS DO NOT APPEARE IN LOG)
                
                var ms = new MemoryStream();
                var writer = XmlWriter.Create(ms);
                request.WriteMessage(writer); // the message was consumed here
                writer.Flush();
                ms.Position = 0;
                var xmlDoc = new XmlDocument();
                xmlDoc.Load(ms);
    
                //DO STUFF with var1 and var2
    
                //The message body is a read-once stream. Message must be recreated
                ms = new MemoryStream();
                xmlDoc.Save(ms);
                ms.Position = 0;
                XmlReader reader = XmlReader.Create(ms);
                Message newMessage = Message.CreateMessage(reader, int.MaxValue, request.Version);
                newMessage.Headers.CopyHeadersFrom(request);
                
    			foreach (string propertyKey in request.Properties.Keys)
                {
                    newMessage.Properties.Add(propertyKey, request.Properties[propertyKey]);
                }
    
                request = newMessage;
                return null;
            }
    
            public void AfterReceiveReply(ref Message reply, object correlationState)
            {
                //Do nothing
            }
        }



    Thursday, July 30, 2015 12:09 PM

Answers

  • Hi Anita doing BizTalk,

    According to this case, I suggest you can disable the SOAP ProcessingBehavior for the service or the endpoint (in your routing config).

    SOAP processing is the process where messages are converted between message versions.

    The Windows Communication Foundation (WCF) Routing Service can convert messages from one protocol to another. If the incoming and outgoing Message Versions are different, a new message of the correct version is created. Processing messages from one MessageVersion to another is accomplished by constructing a new WCF message that contains the body part and relevant headers from the incoming WCF message. Headers that are specific to addressing, or that are understood at the router level, are not used during construction of the new WCF message because these headers are either of a different version (in the case of addressing headers) or have been processed as part of the communication between the client and the router.

    Whether a header is placed in the outbound message is determined by whether or not it was marked as understood as it passed through the incoming channel layer. Headers that are not understood (such as custom headers) are not removed and so pass through the routing service by being copied to the outbound message. The body of the message is copied to the outbound message. The message is then sent out the outbound channel, at which point all of the headers and other envelope data specific to that communication protocol/transport will be created and added.

    Such processing steps take place when the SOAP processing behavior is specified. This <soapProcessing> behavior is an endpoint behavior that is applied to all client (outgoing) endpoints when the Routing Service starts up. default, the <routing> of <serviceBehavior> behavior creates and attaches a new <soapProcessing> behavior with processMessages set to true for each client endpoint. If you have a protocol that the Routing Service does not understand, or wish to override the default processing behavior, you can disable SOAP processing either for the entire Routing Service or just for particular endpoints.  To disable SOAP processing for the entire routing service on all endpoints, set the soapProcessing attribute of the <routing> of <serviceBehavior> behavior to false. To turn off SOAP processing for a particular endpoint, use this behavior and set its processMessages attribute to false, then attach this behavior to the endpoint you do not want the default processing code to run at.  When the <routing> of <serviceBehavior> behavior sets up the Routing Service, it will skip reapplying the endpoint behavior since one already exists.

    For more information,please refer to the following articles:

    1.How to: Inspect or Modify Messages on the Client

    https://msdn.microsoft.com/en-us/library/ms733786.aspx

    2.Message Inspectors

    https://msdn.microsoft.com/en-us/library/aa717047.aspx

    I hope that will be helpful to you.

    Best Regards,

    Tracy Grady



    Wednesday, August 5, 2015 1:41 AM
    Moderator