1

是否可以在 WCF 中更改传入 HTTP 请求的数据?

我已经找到了如何更改 HTTP 方法(使用传入消息的IDispatchOperationSelector和)。HttpRequestMessageProperty

我正在编写可以使用 GET 请求(方法和数据存储在查询字符串中)发出“POST”请求的行为。我可以覆盖 HTTP 方法,但找不到覆盖数据的解决方案。我需要加载存储在查询字符串中的数据并将它们用作 HTTP 正文。

有什么想法吗?

4

2 回答 2

3

您需要重新创建传入消息,以便消息正文包含您要传递的信息。正文可能采用 XML 或 JSON 格式(支持开箱即用)。下面的代码显示了如何做到这一点的一个示例。

public class StackOverflow_10391354
{
    [ServiceContract]
    public class Service
    {
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest)]
        public int Add(int x, int y)
        {
            return x + y;
        }
    }
    class MyWebHttpBehavior : WebHttpBehavior
    {
        protected override WebHttpDispatchOperationSelector GetOperationSelector(ServiceEndpoint endpoint)
        {
            return new MyOperationSelector();
        }
        public override void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            base.ApplyDispatchBehavior(endpoint, endpointDispatcher);
        }
    }
    class MyOperationSelector : WebHttpDispatchOperationSelector
    {
        protected override string SelectOperation(ref Message message, out bool uriMatched)
        {
            HttpRequestMessageProperty prop = (HttpRequestMessageProperty)message.Properties[HttpRequestMessageProperty.Name];
            if (message.Headers.To.LocalPath.EndsWith("/Add") && prop.Method == "GET")
            {
                prop.Method = "POST";
                uriMatched = true;
                message = CreateBodyMessage(message);
                return "Add";
            }
            else
            {
                return base.SelectOperation(ref message, out uriMatched);
            }
        }

        private Message CreateBodyMessage(Message message)
        {
            HttpRequestMessageProperty prop = message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
            string queryString = prop.QueryString;
            NameValueCollection nvc = HttpUtility.ParseQueryString(queryString);
            StringBuilder sb = new StringBuilder();
            sb.Append('{');
            bool first = true;
            foreach (string key in nvc.Keys)
            {
                if (first)
                {
                    first = false;
                }
                else
                {
                    sb.Append(',');
                }

                sb.Append('\"');
                sb.Append(key);
                sb.Append("\":\"");
                sb.Append(nvc[key]);
                sb.Append('\"');
            }
            sb.Append('}');
            string json = sb.ToString();
            XmlDictionaryReader jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(json), XmlDictionaryReaderQuotas.Max);
            Message result = Message.CreateMessage(MessageVersion.None, null, jsonReader);
            result.Properties.Add(HttpRequestMessageProperty.Name, prop);
            result.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));
            result.Headers.To = message.Headers.To;
            return result;
        }
    }
    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(Service), new WebHttpBinding(), "");
        endpoint.Behaviors.Add(new MyWebHttpBehavior());
        host.Open();
        Console.WriteLine("Host opened");

        WebClient c = new WebClient();
        Console.WriteLine(c.DownloadString(baseAddress + "/Add?x=66&y=88"));

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
于 2012-05-01T03:16:26.717 回答
0

您可以使用消息检查器:http ://weblogs.asp.net/paolopia/archive/2007/08/23/writing-a-wcf-message-inspector.aspx

于 2012-05-01T02:51:59.633 回答