Logging SOAP Raw Response Received by a ClientBase object

前端 未结 2 1336
甜味超标
甜味超标 2021-02-06 08:20

I have an application that uses a ClientBase object generated by a service reference to call a third party WCF SOAP service. Every once in awhile, the service call returns a fau

相关标签:
2条回答
  • 2021-02-06 08:30

    At the ClientBase itself there's no place where you can get that information. But you can add a custom message inspector at the client (IClientMessageInspector) where you can see all the messages that are being received; for those messages you can check the IsFault property, and if true log the message as you want.

    Update: Adding sample code

    using System.ServiceModel.Channels;
    using System.ServiceModel.Dispatcher;
    
    public class StackOverflow_12842014
    {
        [ServiceContract]
        public interface ITest
        {
            [OperationContract]
            string Echo(string text);
        }
        public class Service : ITest
        {
            public string Echo(string text)
            {
                if (text == "throw") throw new ArgumentException("Throwing as requested");
                return text;
            }
        }
        class MyClient : ClientBase<ITest>, ITest
        {
            public MyClient(Binding binding, EndpointAddress address)
                : base(binding, address)
            {
                this.Endpoint.Behaviors.Add(new MyFaultLogger());
            }
    
            public string Echo(string text)
            {
                return this.Channel.Echo(text);
            }
    
            class MyFaultLogger : IEndpointBehavior, IClientMessageInspector
            {
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
                {
                }
    
                public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
                {
                    clientRuntime.MessageInspectors.Add(this);
                }
    
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                }
    
                public void Validate(ServiceEndpoint endpoint)
                {
                }
    
                public void AfterReceiveReply(ref Message reply, object correlationState)
                {
                    if (reply.IsFault)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("Fault received!: {0}", reply);
                        Console.ResetColor();
                    }
                }
    
                public object BeforeSendRequest(ref Message request, IClientChannel channel)
                {
                    return null;
                }
            }
        }
        public static void Test()
        {
            string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
            ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
            host.Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
            host.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
            host.Open();
            Console.WriteLine("Host opened");
    
            MyClient client = new MyClient(new BasicHttpBinding(), new EndpointAddress(baseAddress));
    
            Console.WriteLine(client.Echo("Hello"));
            try
            {
                Console.WriteLine(client.Echo("throw"));
            }
            catch (Exception)
            {
                Console.WriteLine("The fault should have been traced");
            }
    
            client.Close();
    
            Console.Write("Press ENTER to close the host");
            Console.ReadLine();
            host.Close();
        }
    }
    
    0 讨论(0)
  • 2021-02-06 08:33

    You may consider another approach to capture XML - custom MessageEncoder. Unlike IClientMessageInspector it handles original byte content of http body.

    You need to wrap a standard textMessageEncoding with custom message encoder as new binding element and apply that custom binding to endpoint in your config.

    Also you can look how I did it in my project - wrapping textMessageEncoding, logging encoder, custom binding element and config.

    0 讨论(0)
提交回复
热议问题