none
IDispatchMessageInspector question RRS feed

  • Question

  • Hi guys,

    i have a simple Wcf like this:

    public class MessageBusService : IMessageBus
    {
        public string Send(string message)
        {
            return message;
        }
    }

    and i have implemented IDispatchMessageInspector in my class like this:


        public class DispatchMessageInspector : IDispatchMessageInspector
        {
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                Logger.Write($"###### Inside {nameof(AfterReceiveRequest)} ########");
    
                return null;
            }
    
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
    
            }
        }

    then i implemeted BehaviorExtensionElement and IServiceBehavior in my class InspectorInserter like this:

    public class InspectorInserter : BehaviorExtensionElement, IServiceBehavior
        {
            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
                
            }
    
            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
                BindingParameterCollection bindingParameters)
            {
                Logger.Write($"###### Inside {nameof(AddBindingParameters)} ########"); 
                return;
            }
    
            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
                Logger.Write($"###### Inside {nameof(ApplyDispatchBehavior)} ########");
    
                foreach (var channelDispatcherBase in serviceHostBase.ChannelDispatchers)
                {
                    var chDisp = (ChannelDispatcher) channelDispatcherBase;
    
                    foreach (var epDisp in chDisp.Endpoints)
                    {
                        epDisp.DispatchRuntime.MessageInspectors.Add(new DispatchMessageInspector());
                    }
                }
            }
    
            protected override object CreateBehavior()
            {
                return this;
            }
    
            public override Type BehaviorType
            {
                get { return typeof(InspectorInserter); }
            }
        }


    In my Web.config i have this configuration:

    <?xml version="1.0"?> <configuration> <appSettings> <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.6.1" /> <httpRuntime targetFramework="4.6.1"/> </system.web> <system.serviceModel> <services> <service name="DispatchMessageInspector.MessageBusService" behaviorConfiguration="myBehavior"> <endpoint bindingConfiguration="myBinding" binding="basicHttpBinding" contract="DispatchMessageInspector.IMessageBus"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="myBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true"/> <serviceInterceptors /> </behavior> </serviceBehaviors> </behaviors> <bindings> <basicHttpBinding> <binding name="myBinding"> <security mode="None"/> </binding> </basicHttpBinding> </bindings> <protocolMapping> <add binding="basicHttpsBinding" scheme="https" /> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> <extensions> <behaviorExtensions> <add name="serviceInterceptors" type="DispatchMessageInspector.InspectorInserter, DispatchMessageInspector, Version=1.0.0.0, Culture=neutral"/> </behaviorExtensions> </extensions> </system.serviceModel> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/> <directoryBrowse enabled="true"/> </system.webServer> </configuration>

    Examining my log:

    ###### Inside AddBindingParameters ########
    ###### Inside ApplyDispatchBehavior ########
    ###### Inside AfterReceiveRequest ########
    ###### Inside AddBindingParameters ########
    ###### Inside AfterReceiveRequest ########
    ###### Inside AfterReceiveRequest ########
    ###### Inside AfterReceiveRequest ########

    i noticed that method AfterReceiveRequest is called more times without any request. Why? Which is the mechanism that invoke this method?

    Thank you

    Wednesday, February 13, 2019 10:33 AM

All replies

  • Hi Pampua84,

    My results here are a little different from yours. It seems that everything works well. how do you apply the DispatchMessageInspector to make it valid so that the soap message could be inspected?

    Here is my example, wish it is useful to you.
    Server side.

    class Program
        {
            static void Main(string[] args)
            {
                Uri uri = new Uri("http://localhost:1300");
                BasicHttpBinding binding = new BasicHttpBinding();
                using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
                {
                    sh.AddServiceEndpoint(typeof(IService), binding, "");
                    ServiceMetadataBehavior smb;
                    smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                    if (smb==null)
                    {
                        smb = new ServiceMetadataBehavior()
                        {
                            HttpGetEnabled = true
                        };
                        sh.Description.Behaviors.Add(smb);
                    }
                    Binding binding1 = MetadataExchangeBindings.CreateMexHttpBinding();
                    sh.AddServiceEndpoint(typeof(IMetadataExchange), binding1, "MEX");
                    sh.Open();
                    Console.WriteLine("service is ready...");
                    Console.ReadLine();
                    sh.Close();
                }
    
            }
        }
        [ServiceContract(Namespace ="mydomain")]
        [CustomContractBehavior]
        public interface IService
        {
            [OperationContract]
            string SayHello();
        }
        public class MyService : IService
        {
            public string SayHello()
            {
                return "Hello Stranger";
            }
        }
        public class ServerMessageLogger : IDispatchMessageInspector
        {
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                string displayText = $"Server has received the following message:\n{request}\n";
                Console.WriteLine(nameof(AfterReceiveRequest));
                return null;
            }
    
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
                string displayText = $"Server has replied the following message:\n{reply}\n";
                Console.WriteLine(nameof(BeforeSendReply));
    
            }
        }
        public class CustomContractBehaviorAttribute : Attribute, IContractBehavior,IContractBehaviorAttribute
        {
            public Type TargetContract => typeof(IService);
    
            public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
            {
                Console.WriteLine(nameof(AddBindingParameters));
                return;
            }
    
            public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
            {
                return;
            }
    
            public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
            {
                Console.WriteLine(nameof(ApplyDispatchBehavior));
                dispatchRuntime.MessageInspectors.Add(new ServerMessageLogger());
            }
    
            public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
            {
                return;
            }
    }
    

    Client side(adding service reference generates the client proxy class)

    ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
                try
                {
                    var result = client.SayHello();
                    Console.WriteLine(result);
                }
                catch (Exception)
                {
    
                    throw;
                }
    

    Result.

    Before hosting the service, the application custom behavior feature is applied to make ServerMessageLogger invoked correctly. When the client invokes the service, the server processes and sends a response correctly.
    Best Regards

    Abraham

                            
    Thursday, February 14, 2019 6:41 AM
    Moderator