WCF如何在请求中添加自定义HTTP头部

4

我在WCF服务上遇到了消息解析问题。

我运行了WCF应用程序的服务器端。另一家公司向我发送了这样的HTTP POST请求:

POST /telemetry/telemetryWebService HTTP/1.1
Host: 192.168.0.160:12123
Content-Length: 15870
Expect: 100-continue
Connection: Keep-Alive

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security> ... </wsse:Security>
  </soapenv:Header>
<soapenv:Body>
...
</soapenv:Body>
</soapenv:Envelope>

在这个HTTP请求中,缺少两个重要的标头:Soap ActionContent-type。这就是为什么我的服务无法正确处理此请求的原因。

我需要捕获请求直到开始处理并手动添加这些标头。

我已经尝试过IDispatchMessageInspector,但没有任何结果。


3
请问您能否告诉我们为什么使用IDispatchMessageInspector没有成功,可以展示一下相关代码和出现的问题/错误吗?请注意,您随时可以编辑您的问题。(另外,我不确定在客户端解决这个问题是否可行?) - Jeroen
1
我感同身受 :P “嘿,让我们使用这个SOAP东西。它只是一堆XML,对吧?等等,什么?你的意思是有一个规范吗?还有工具可以为你生成正确的代码?” - anton.burger
2个回答

2

在处理SOAP消息时,服务器端的分派是根据soap action头执行的,该头指示分派程序应该处理消息的相应方法。

有时soap action为空或无效(Java互操作)。

我认为最好的选择是实现一个IDispatchOperationSelector。通过这种方式,您可以覆盖服务器分配传入消息到操作的默认方式。

在下面的示例中,分派程序将映射SOAP正文中第一个元素的名称到操作名称,以便将消息转发进行处理。

 public class DispatchByBodyElementOperationSelector : IDispatchOperationSelector
    {
        #region fields

        private const string c_default = "default";
        readonly Dictionary<string, string> m_dispatchDictionary;

        #endregion

        #region constructor

        public DispatchByBodyElementOperationSelector(Dictionary<string, string> dispatchDictionary)
        {
            m_dispatchDictionary = dispatchDictionary;
            Debug.Assert(dispatchDictionary.ContainsKey(c_default), "dispatcher dictionary must contain a default value");
        }

        #endregion

        public string SelectOperation(ref Message message)
        {
            string operationName = null;
            var bodyReader = message.GetReaderAtBodyContents();
            var lookupQName = new
               XmlQualifiedName(bodyReader.LocalName, bodyReader.NamespaceURI);

            // Since when accessing the message body the messageis marked as "read"
            // the operation selector creates a copy of the incoming message 
            message = CommunicationUtilities.CreateMessageCopy(message, bodyReader);

            if (m_dispatchDictionary.TryGetValue(lookupQName.Name, out operationName))
            {
                return operationName;
            }
            return m_dispatchDictionary[c_default];
        }
    }

谢谢。这是一个正确的答案。它可以工作,但并不适用于所有问题。 - Sergey

0

谢谢大家。

1) 你需要创建自己的自定义消息编码器,可以默认创建Content-type。你可以在这里点击这里查看示例。

2) 你需要创建自定义消息过滤器,因为你需要跳过没有SoapAction的消息。

public class CustomFilter : MessageFilter
{
    private int minSize;
    private int maxSize;
    public CustomFilter()
        : base()
    {

    }
    public CustomFilter(string paramlist)
        : base()
    {
        string[] sizes = paramlist.Split(new char[1] { ',' });
        minSize = Convert.ToInt32(sizes[0]);
        maxSize = Convert.ToInt32(sizes[1]);
    }
    public override bool Match(System.ServiceModel.Channels.Message message)
    {
        return true;
    }
    public override bool Match(MessageBuffer buffer)
    {
        return true;
    }
}

3) 你需要创建自定义消息选择器,将传入的消息分配给操作。 Cybermaxs 的示例非常好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接