访问WCF编码器中的传入消息属性(OperationContext.Current为null)

时间:2014-04-22 10:53:07

标签: c# wcf

我正在编写自定义WCF消息编码器,当请求消息进入此编码器时,我需要访问WCF消息属性(或标题)。
问题是OperationContext.Current为null,我无法访问我的Encoder类中的实际WCF消息。

有没有办法做到这一点? (知道我不能完全控制客户)。

祝你好运

1 个答案:

答案 0 :(得分:2)

以下是自定义MessageEncoder的演示。

此演示的目的:客户端将字符串属性保存到消息中,服务器程序将在接收消息时打印出该字符串。

共同部分:

public class MyMessageEncoder : MessageEncoder {
    public MessageEncoder InnerMessageEncoder { get; set; }
    public String Greeting { get; private set; }

    public MyMessageEncoder(MessageEncoder innerMessageEncoder, String greeting) {
        this.InnerMessageEncoder = innerMessageEncoder;
        this.Greeting = greeting;
    }

    public override string ContentType {
        get { return this.InnerMessageEncoder.ContentType; }
    }

    public override string MediaType {
        get { return this.InnerMessageEncoder.MediaType; }
    }

    public override MessageVersion MessageVersion {
        get { return this.InnerMessageEncoder.MessageVersion; }
    }

    public override T GetProperty<T>() {
        return this.InnerMessageEncoder.GetProperty<T>();
    }

    public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType) {
        Message message = this.InnerMessageEncoder.ReadMessage(buffer, bufferManager, contentType);
        Console.WriteLine("greeting = " + message.Properties["greeting"].ToString());
        return message;
    }

    public override Message ReadMessage(System.IO.Stream stream, int maxSizeOfHeaders, string contentType) {
        Message message = this.InnerMessageEncoder.ReadMessage(stream, maxSizeOfHeaders, contentType);
        Console.WriteLine("greeting = " + message.Properties["greeting"].ToString());
        return message;
    }

    public override ArraySegment<byte> WriteMessage(
        Message message, int maxMessageSize, 
        BufferManager bufferManager, int messageOffset) {

        message.Properties["greeting"] = this.Greeting;
        return this.InnerMessageEncoder.WriteMessage(
            message, maxMessageSize, bufferManager, messageOffset);
    }

    public override void WriteMessage(Message message, System.IO.Stream stream) {
        message.Properties["greeting"] = this.Greeting;
        this.InnerMessageEncoder.WriteMessage(message, stream);
    }
}

public class MyMessageEncoderFactory : MessageEncoderFactory {
        public MessageEncoderFactory InnerMessageEncoderFactory { get; private set; }
        public String Greeting { get; private set; }

        public MyMessageEncoderFactory(MessageEncoderFactory innerMessageEncoderFactory, String greeting) {
            this.InnerMessageEncoderFactory = innerMessageEncoderFactory;
            this.Greeting = greeting;
        }

        public override MessageEncoder Encoder {
            get { 
                return new MyMessageEncoder(
                    this.InnerMessageEncoderFactory.Encoder, this.Greeting); 
            }
        }

        public override MessageVersion MessageVersion {
            get { return this.InnerMessageEncoderFactory.MessageVersion; }
        }
    }


public class MyTextEncodingElement: BindingElementExtensionElement {
        [ConfigurationProperty("greeting")]
        public String Greeting {
            get { return (String)this["greeting"]; }
            set { this["greeting"] = value; }
        }

        [ConfigurationProperty("textEncoding")]
        public TextMessageEncodingElement TextEncoding {
            get { return (TextMessageEncodingElement)this["textEncoding"]; }
            set { this["textEncoding"] = value; }
        }

        public override Type BindingElementType {
            get { return typeof(MyTextMessageEncodingBindingElement); }
        }

        protected override BindingElement CreateBindingElement() {
            var textBindingElement = new TextMessageEncodingBindingElement();
            if (this.TextEncoding != null) {
                this.TextEncoding.ApplyConfiguration(textBindingElement);
            }
            return new MyTextMessageEncodingBindingElement(textBindingElement, this.Greeting);
        }
    }

public class MyTextMessageEncodingBindingElement : MessageEncodingBindingElement {
        public TextMessageEncodingBindingElement TextEncodingElement { get; private set; }
        public String Greeting { get; private set; }

        private MyTextMessageEncodingBindingElement() {

        }

        public MyTextMessageEncodingBindingElement(
            TextMessageEncodingBindingElement textEncodingElement, String greeting) {
            this.TextEncodingElement = textEncodingElement;
            this.Greeting = greeting;
        }

        public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context) {
            context.BindingParameters.Add(this);
            return base.BuildChannelFactory<TChannel>(context);
        }

        public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) {
            context.BindingParameters.Add(this);
            return base.BuildChannelListener<TChannel>(context);
        }

        public override MessageEncoderFactory CreateMessageEncoderFactory() {
            return new MyMessageEncoderFactory(
                this.TextEncodingElement.CreateMessageEncoderFactory(),
                this.Greeting);
        }

        public override MessageVersion MessageVersion {
            get {
                return this.TextEncodingElement.MessageVersion;
            }
            set {
                this.TextEncodingElement.MessageVersion = value;
            }
        }

        public override BindingElement Clone() {
            var textEncodingElement = new TextMessageEncodingBindingElement() {
                MaxReadPoolSize = this.TextEncodingElement.MaxReadPoolSize,
                MaxWritePoolSize = this.TextEncodingElement.MaxWritePoolSize,
                MessageVersion = this.TextEncodingElement.MessageVersion,
                WriteEncoding = this.TextEncodingElement.WriteEncoding
            };
            return new MyTextMessageEncodingBindingElement(
                textEncodingElement, this.Greeting);
        }
    }

服务器程序:

[ServiceContract(Name="CalculatorService", Namespace="http://www.artech.com")]
    public interface ICalculatorService {
        [OperationContract]
        int Add(int x, int y);
    }

public class CalculatorService : ICalculatorService {
        public Int32 Add(Int32 x, Int32 y) {
            Console.WriteLine("{0}: service method called (x = {1}, y = {2})",
                Thread.CurrentThread.ManagedThreadId, x, y);
            return x + y;
        }
    }

class Program {
        static void Main(string[] args) {
            using (var serviceHost = new ServiceHost(typeof(CalculatorService))) {
                serviceHost.Opened += delegate {
                    Console.WriteLine("{0}: service started", 
                        Thread.CurrentThread.ManagedThreadId);
                };
                serviceHost.Open();

                Console.Read();
            }
        }
    }

服务器配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <extensions>
            <bindingElementExtensions>
                <add name="myTextEncoding" 
                     type="Common.MyTextEncodingElement, Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
            </bindingElementExtensions>
        </extensions>
        <bindings>
            <customBinding>
                <binding name="myTextEncoding">
                    <myTextEncoding greeting="we dont use this">
                        <textEncoding maxReadPoolSize="64"
                                      maxWritePoolSize="16"
                                      messageVersion="Soap11"
                                      writeEncoding="utf-8">
                            <readerQuotas maxArrayLength="16384"
                                          maxBytesPerRead="4096"
                                          maxDepth="32"
                                          maxStringContentLength="8192"
                                          maxNameTableCharCount="16384" />
                        </textEncoding>
                    </myTextEncoding>
                    <httpTransport/>
                </binding>
            </customBinding>
        </bindings>
        <services>
            <service name="WcfService.CalculatorService">
                <endpoint address="http://127.0.0.1:3722/calculatorservice" 
                          binding="customBinding"
                          bindingConfiguration="myTextEncoding"
                          contract="Contract.ICalculatorService" />
            </service>
        </services>
    </system.serviceModel>
</configuration>

客户方:

class Program {
        static void Main(string[] args) {
            using (var channelFactory =
                new ChannelFactory<ICalculatorService>("calculatorservice")) {

                ICalculatorService proxy = channelFactory.CreateChannel();
                Console.WriteLine(proxy.Add(1, 2));
                Console.Read();
            }
            Console.Read();
        }
    }

客户端配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <extensions>
            <bindingElementExtensions>
                <add name="myTextEncoding"
                     type="Common.MyTextEncodingElement, Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
            </bindingElementExtensions>
        </extensions>
        <bindings>
            <customBinding>
                <binding name="myTextEncoding">
                    <myTextEncoding greeting="hello client">
                        <textEncoding maxReadPoolSize="64"
                                      maxWritePoolSize="16"
                                      messageVersion="Soap11"
                                      writeEncoding="utf-8">
                            <readerQuotas maxArrayLength="16384"
                                          maxBytesPerRead="4096"
                                          maxDepth="32"
                                          maxStringContentLength="8192"
                                          maxNameTableCharCount="16384" />
                        </textEncoding>
                    </myTextEncoding>
                    <httpTransport/>
                </binding>
            </customBinding>
        </bindings>
        <client>
            <endpoint name="calculatorservice"
                      address="http://127.0.0.1:3722/calculatorservice"
                      binding="customBinding"
                      bindingConfiguration="myTextEncoding"
                      contract="Contract.ICalculatorService"/>
        </client>
    </system.serviceModel>
</configuration>