7

是否可以在 上设置标题WebChannelFactory?如果我使用一个WebClient对象,我可以这样做:

WebClient client = new WebClient();
client.Headers.Add("referer", "http://stackoverflow.com");
client.Headers.Add("user-agent", "Mozilla/5.0");

但是我还没有找到一种方法来修改WebChannelFactory.

4

1 回答 1

10

该类WebChannelFactory本身不采用任何 HTTP 标头,但您可以将它们添加到当前WebOperationContext,因为您创建了一个新的范围以使其工作 - 见下文。

WebChannelFactory<ICalculator> factory = new WebChannelFactory<ICalculator>(new Uri(baseAddress));
ICalculator proxy = factory.CreateChannel();
using (new OperationContextScope((IContextChannel)proxy))
{
    WebOperationContext.Current.OutgoingRequest.Headers.Add("referer", "http://stackoverflow.com");
    WebOperationContext.Current.OutgoingRequest.Headers.Add("user-agent", "Mozilla/5.0");
    Console.WriteLine("Add: {0}", proxy.Add(33, 55));
    Console.WriteLine();
}

using (new OperationContextScope((IContextChannel)proxy))
{
    WebOperationContext.Current.OutgoingRequest.Headers.Add("referer", "http://stackoverflow.com");
    WebOperationContext.Current.OutgoingRequest.Headers.Add("user-agent", "Mozilla/5.0");
    Console.WriteLine("Subtract: {0}", proxy.Subtract(44, 33));
    Console.WriteLine();
}

这可行,但它相当冗长 - 如果您想向其中添加传出标头,您基本上需要为每个调用创建一个新范围。

另一种选择是将客户端包装在客户端类中,以便为您添加范围和标头。使用派生自的类ClientBase<T>是一种简单的方法。下面的代码是这个问题的完整示例,具有两个选项(直接使用范围,使用客户端基派生类)用于在来自WebChannelFactory.

public class StackOverflow_10388746
{
    [ServiceContract]
    public interface ICalculator
    {
        [WebGet]
        int Add(int x, int y);
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        int Subtract(int x, int y);
    }
    public class Service : ICalculator
    {
        public int Add(int x, int y)
        {
            PrintHeaders("Add");
            return x + y;
        }
        public int Subtract(int x, int y)
        {
            PrintHeaders("Subtract");
            return x - y;
        }
        void PrintHeaders(string operation)
        {
            Console.WriteLine("Incoming HTTP headers for operation '{0}'", operation);
            foreach (var header in WebOperationContext.Current.IncomingRequest.Headers.AllKeys)
            {
                Console.WriteLine("  {0}: {1}", header, WebOperationContext.Current.IncomingRequest.Headers[header]);
            }
        }
    }
    public class MyWebClient : ClientBase<ICalculator>, ICalculator
    {
        Dictionary<string, string> outgoingHeaders = new Dictionary<string, string>();

        public MyWebClient(Uri baseAddress)
            : base(new WebHttpBinding(), new EndpointAddress(baseAddress))
        {
            this.Endpoint.Behaviors.Add(new WebHttpBehavior());
        }

        #region ICalculator Members

        public int Add(int x, int y)
        {
            using (new OperationContextScope(this.InnerChannel))
            {
                foreach (var headerName in this.outgoingHeaders.Keys)
                {
                    WebOperationContext.Current.OutgoingRequest.Headers.Add(headerName, this.outgoingHeaders[headerName]);
                }

                this.outgoingHeaders.Clear();
                return this.Channel.Add(x, y);
            }
        }

        public int Subtract(int x, int y)
        {
            using (new OperationContextScope(this.InnerChannel))
            {
                foreach (var headerName in this.outgoingHeaders.Keys)
                {
                    WebOperationContext.Current.OutgoingRequest.Headers.Add(headerName, this.outgoingHeaders[headerName]);
                }

                this.outgoingHeaders.Clear();
                return this.Channel.Subtract(x, y);
            }
        }

        #endregion

        public void AddOutgoingHeader(string name, string value)
        {
            this.outgoingHeaders.Add(name, value);
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        WebChannelFactory<ICalculator> factory = new WebChannelFactory<ICalculator>(new Uri(baseAddress));
        ICalculator proxy = factory.CreateChannel();
        using (new OperationContextScope((IContextChannel)proxy))
        {
            WebOperationContext.Current.OutgoingRequest.Headers.Add("referer", "http://stackoverflow.com");
            WebOperationContext.Current.OutgoingRequest.Headers.Add("user-agent", "Mozilla/5.0");
            Console.WriteLine("Add: {0}", proxy.Add(33, 55));
            Console.WriteLine();
        }

        using (new OperationContextScope((IContextChannel)proxy))
        {
            WebOperationContext.Current.OutgoingRequest.Headers.Add("referer", "http://stackoverflow.com");
            WebOperationContext.Current.OutgoingRequest.Headers.Add("user-agent", "Mozilla/5.0");
            Console.WriteLine("Subtract: {0}", proxy.Subtract(44, 33));
            Console.WriteLine();
        }

        MyWebClient client = new MyWebClient(new Uri(baseAddress));
        client.AddOutgoingHeader("referer", "http://stackoverflow.com");
        client.AddOutgoingHeader("user-agent", "Mozilla/5.0");
        Console.WriteLine("Add (via client): {0}", client.Add(44, 77));
        Console.WriteLine();

        client.AddOutgoingHeader("referer", "http://stackoverflow.com/another");
        client.AddOutgoingHeader("user-agent", "Mozilla/5.0-b");
        Console.WriteLine("Add (via client): {0}", client.Subtract(44, 77));
        Console.WriteLine();

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
于 2012-05-02T19:26:37.380 回答