2012-09-30 185 views
4

我在WCF服務上解析消息時遇到問題。 我跑了WCF應用程序的服務器端。另一家公司給我發這樣的HTTP POST請求:WCF將自定義HTTP頭添加到請求中

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動作內容類型。那就是爲什麼我的服務不能正確處理此請求。

我需要趕上請求,直到它開始處理並手動添加這些標頭。

我已經試過IDispatchMessageInspector,但沒有任何結果。

+3

你能告訴我們爲什麼使用'IDispatchMessageInspector'的嘗試不起作用,或許顯示(一個樣本)的代碼和它的問題/錯誤?請注意,您可以隨時編輯您的問題。 (PS。我不認爲在客戶端修復這個問題是一種選擇嗎?) – Jeroen

+1

我感覺到你的痛苦:P *「嘿,讓我們使用這個SOAP的東西,它只是一堆XML,對吧?這意味着它有一個** spec **嗎?還有一些工具可以生成代碼來爲**做正確的事情**「* – shambulator

回答

0

謝謝大家。

1)您需要創建自己的自定義消息編碼器,您可以在其中默認創建Content-type。 Yщu可以通過例子閱讀它here

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)您需要爲以操作分配傳入郵件創建自定義消息選擇跳過消息。 Cyber​​maxs的例子非常好。

2

處理SOAP消息時,服務器端的調度是根據soap動作頭來完成的,它指示調度員應該處理消息的相應方法是什麼。

有時候soap動作是空的或無效的(java interop)。

我認爲你最好的選擇是實現一個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]; 
     } 
    } 
+0

謝謝。這是一個合適的答案。它有效,但不是所有問題。 – Sergey

相關問題