从客户端扩展WCF服务调用

时间:2011-09-20 11:16:13

标签: wcf

我正在使用我的WCF服务与我无法控制的外部Web服务进行通信。现在,我想为被调用的操作添加一个行为,这样,无论何时无法与服务通信,都应该通过特定的存储过程将某些内容记录到数据库中(在这种情况下,没有NLog / Log4Net,它是真的是一个存储过程)。但是,我不想在调用服务的每个方法中为此编写代码,因此我认为行为应该更合适。我怎样才能完成这个?

1 个答案:

答案 0 :(得分:2)

您可以在客户端使用IClientMessageInspector,只要在收到回复后收到呼叫,它就会检查响应是否成功(即故障)。如果不是,您可以适当地记录它。下面的代码显示了客户端消息检查器执行此操作的示例。您可以在http://blogs.msdn.com/b/carlosfigueira/archive/2011/04/19/wcf-extensibility-message-inspectors.aspx找到有关消息检查员的更多信息。

public class StackOverflow_7484237
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        string Echo(string text);
    }
    public class Service : ITest
    {
        public string Echo(string text)
        {
            if (text == "throw")
            {
                throw new ArgumentException("This will cause a fault to be received at the client");
            }
            else
            {
                return text;
            }
        }
    }
    public class MyInspector : 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.WriteLine("Log this fault: {0}", reply);
            }
        }

        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.AddServiceEndpoint(typeof(ITest), new BasicHttpBinding(), "");
        host.Open();
        Console.WriteLine("Host opened");

        var factory = new ChannelFactory<ITest>(new BasicHttpBinding(), new EndpointAddress(baseAddress));
        factory.Endpoint.Behaviors.Add(new MyInspector());
        var proxy = factory.CreateChannel();

        Console.WriteLine(proxy.Echo("This won't throw"));

        try
        {
            Console.WriteLine(proxy.Echo("throw"));
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: {0}", e);
        }

        ((IClientChannel)proxy).Close();
        factory.Close();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}