如何使用MessageInspector在WCF上实现编排



我有一个WCF服务,我使用MessageInspector(inherit IDispatchMessageInspecter)检查它

我想在运行服务之前做一些事情,结果是不想运行服务。

我想阻止客户来电,但客户没有收到异常。

你能帮我吗

这个场景看起来像MSDN WCF论坛上题为"IDispatchMessageInspector.AfterReceiveRequest-跳过操作并手动生成自定义响应"的帖子。如果这正是您所需要的(当您在检查器中收到消息时,您决定跳过服务操作,但向客户端返回消息,客户端不应该看到异常),那么这个答案也应该适用于您。请注意,您需要以与客户端期望的格式相同的格式创建响应消息,否则将出现异常。

这段代码使用三个(许多)WCF扩展点来实现该场景,一个消息检查器(正如您所提到的)、一个消息格式化程序和一个操作调用程序。我在一个正在进行的关于WCF可扩展性的系列文章中写过关于它们的博客http://blogs.msdn.com/b/carlosfigueira/archive/2011/03/14/wcf-extensibility.aspx.

public class Post_55ef7692_25dc_4ece_9dde_9981c417c94a
{
    [ServiceContract(Name = "ITest", Namespace = "http://tempuri.org/")]
    public interface ITest
    {
        [OperationContract]
        string Echo(string text);
    }
    public class Service : ITest
    {
        public string Echo(string text)
        {
            return text;
        }
    }
    static Binding GetBinding()
    {
        BasicHttpBinding result = new BasicHttpBinding();
        return result;
    }
    public class MyOperationBypasser : IEndpointBehavior, IOperationBehavior
    {
        internal const string SkipServerMessageProperty = "SkipServer";
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
        }
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyInspector(endpoint));
        }
        public void Validate(ServiceEndpoint endpoint)
        {
        }
        public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
        {
        }
        public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
        {
        }
        public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
        {
            dispatchOperation.Formatter = new MyFormatter(dispatchOperation.Formatter);
            dispatchOperation.Invoker = new MyInvoker(dispatchOperation.Invoker);
        }
        public void Validate(OperationDescription operationDescription)
        {
        }
        class MyInspector : IDispatchMessageInspector
        {
            ServiceEndpoint endpoint;
            public MyInspector(ServiceEndpoint endpoint)
            {
                this.endpoint = endpoint;
            }
            public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
            {
                Message result = null;
                HttpRequestMessageProperty reqProp = null;
                if (request.Properties.ContainsKey(HttpRequestMessageProperty.Name))
                {
                    reqProp = request.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
                }
                if (reqProp != null)
                {
                    string bypassServer = reqProp.Headers["X-BypassServer"];
                    if (!string.IsNullOrEmpty(bypassServer))
                    {
                        result = Message.CreateMessage(request.Version, this.FindReplyAction(request.Headers.Action), new OverrideBodyWriter(bypassServer));
                    }
                }
                return result;
            }
            public void BeforeSendReply(ref Message reply, object correlationState)
            {
                Message newResult = correlationState as Message;
                if (newResult != null)
                {
                    reply = newResult;
                }
            }
            private string FindReplyAction(string requestAction)
            {
                foreach (var operation in this.endpoint.Contract.Operations)
                {
                    if (operation.Messages[0].Action == requestAction)
                    {
                        return operation.Messages[1].Action;
                    }
                }
                return null;
            }
            class OverrideBodyWriter : BodyWriter
            {
                string bypassServerHeader;
                public OverrideBodyWriter(string bypassServerHeader)
                    : base(true)
                {
                    this.bypassServerHeader = bypassServerHeader;
                }
                protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
                {
                    writer.WriteStartElement("EchoResponse", "http://tempuri.org/");
                    writer.WriteStartElement("EchoResult");
                    writer.WriteString(this.bypassServerHeader);
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                }
            }
        }
        class MyFormatter : IDispatchMessageFormatter
        {
            IDispatchMessageFormatter originalFormatter;
            public MyFormatter(IDispatchMessageFormatter originalFormatter)
            {
                this.originalFormatter = originalFormatter;
            }
            public void DeserializeRequest(Message message, object[] parameters)
            {
                if (message.Properties.ContainsKey(MyOperationBypasser.SkipServerMessageProperty))
                {
                    Message returnMessage = message.Properties[MyOperationBypasser.SkipServerMessageProperty] as Message;
                    OperationContext.Current.IncomingMessageProperties.Add(MyOperationBypasser.SkipServerMessageProperty, returnMessage);
                    OperationContext.Current.OutgoingMessageProperties.Add(MyOperationBypasser.SkipServerMessageProperty, returnMessage);
                }
                else
                {
                    this.originalFormatter.DeserializeRequest(message, parameters);
                }
            }
            public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result)
            {
                if (OperationContext.Current.OutgoingMessageProperties.ContainsKey(MyOperationBypasser.SkipServerMessageProperty))
                {
                    return null;
                }
                else
                {
                    return this.originalFormatter.SerializeReply(messageVersion, parameters, result);
                }
            }
        }
        class MyInvoker : IOperationInvoker
        {
            IOperationInvoker originalInvoker;
            public MyInvoker(IOperationInvoker originalInvoker)
            {
                if (!originalInvoker.IsSynchronous)
                {
                    throw new NotSupportedException("This implementation only supports synchronous invokers");
                }
                this.originalInvoker = originalInvoker;
            }
            public object[] AllocateInputs()
            {
                return this.originalInvoker.AllocateInputs();
            }
            public object Invoke(object instance, object[] inputs, out object[] outputs)
            {
                if (OperationContext.Current.IncomingMessageProperties.ContainsKey(MyOperationBypasser.SkipServerMessageProperty))
                {
                    outputs = null;
                    return null; // message is stored in the context
                }
                else
                {
                    return this.originalInvoker.Invoke(instance, inputs, out outputs);
                }
            }
            public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
            {
                throw new NotSupportedException();
            }
            public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
            {
                throw new NotSupportedException();
            }
            public bool IsSynchronous
            {
                get { return true; }
            }
        }
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), GetBinding(), "");
        endpoint.Behaviors.Add(new MyOperationBypasser());
        foreach (var operation in endpoint.Contract.Operations)
        {
            operation.Behaviors.Add(new MyOperationBypasser());
        }
        host.Open();
        Console.WriteLine("Host opened");
        ChannelFactory<ITest> factory = new ChannelFactory<ITest>(GetBinding(), new EndpointAddress(baseAddress));
        ITest proxy = factory.CreateChannel();
        Console.WriteLine(proxy.Echo("Hello"));
        Console.WriteLine("And now with the bypass header");
        using (new OperationContextScope((IContextChannel)proxy))
        {
            HttpRequestMessageProperty httpRequestProp = new HttpRequestMessageProperty();
            httpRequestProp.Headers.Add("X-BypassServer", "This message will not reach the service operation");
            OperationContext.Current.OutgoingMessageProperties.Add(
                HttpRequestMessageProperty.Name,
                httpRequestProp);
            Console.WriteLine(proxy.Echo("Hello"));
        }
        ((IClientChannel)proxy).Close();
        factory.Close();
        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}

相关内容

  • 没有找到相关文章

最新更新