2016-09-29 8 views
2

我試圖通過WCF將自定義標題添加到每個傳出的請求消息。WCF使用AddressHeader.CreateAddressHeader()方法添加標題問題

我創建的標題對象那樣:

EndpointAddressBuilder eab = new EndpointAddressBuilder(combinedService.Endpoint.Address); 
AddressHeader addressHeader = AddressHeader.CreateAddressHeader("HeaderData", String.Empty, "String data"); 
eab.Headers.Add(addressHeader); 
combinedService.Endpoint.Address = eab.ToEndpointAddress(); 

我用在兩個位置這個確切的代碼在我的代碼,一個運作良好,但其他沒有。 問題是在下面的代碼行:

AddressHeader addressHeader = AddressHeader.CreateAddressHeader("HeaderData", String.Empty, "String data"); 

當它工作(通過頭數據成功)創建的對象看起來就像是: enter image description here

但是當它不工作時,創建的對象看起來像這樣: enter image description here

完全相同的方法,但兩個位置代碼調用產生不同的結果。

是否有任何方法我應該在addressHeader對象上執行以強制其序列化對象?也許是這樣的:Flush()

我知道我可以使用幾種衆所周知的添加自定義標題的模式,例如「自定義行爲」,「客戶端消息檢查器」等等......但我有要求在我們發送之前將其添加到特定點消息。

+0

這個問題有何進展? – Glenn

+1

@Glenn你可以看看答案。 – Jacob

回答

1

我終於找到了解決辦法。

我只是按照步驟thisthis優秀,詳細和簡單的文章。

儘管這段代碼看起來很長並且很複雜,但這是處理WCF中頭數據最正確的方式。所以它最終值得。

您只需配置處理WCF標頭的自定義行爲。

這是怎麼一回事呢:

客戶端:

public class FillHeaderDataBehaviourExtension : BehaviorExtensionElement, IEndpointBehavior 
{ 
    #region BehaviorExtensionElement Implementation 
    public override Type BehaviorType 
    { 
     get 
     { 
      return typeof(FillHeaderDataBehaviourExtension); 
     } 
    } 
    protected override object CreateBehavior() 
    { 
     return this; 
    } 
    #endregion 

    #region IServiceBehaviour Implementation 
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 
    } 
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 

    } 
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
    } 

    public void Validate(ServiceEndpoint endpoint) 
    { 
    } 
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { 
    } 
    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
    { 
    } 
    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
     clientRuntime.ClientMessageInspectors.Add(new MessageInspector()); 
    } 
    #endregion 
} 

public class MessageInspector : IClientMessageInspector 
{ 
    public object BeforeSendRequest(ref Message request, IClientChannel channel) 
    { 
     MessageHeader header = MessageHeader.CreateHeader("HeaderData", String.Empty, HeaderDataVM.GetInstance().GetBaseInstance()); 
     request.Headers.Add(header); // There is no need for checking if exist before adding. Every request has it's own headers. 

     return null; 
    } 
    public void AfterReceiveReply(ref Message reply, object correlationState) 
    { 
    } 
} 

服務器端:

public class ExtractHeadersBehaviourExtension : BehaviorExtensionElement, IServiceBehavior 
{ 
    #region BehaviorExtensionElement Implementation 
    public override Type BehaviorType 
    { 
     get 
     { 
      return typeof(ExtractHeadersBehaviourExtension); 
     } 
    } 
    protected override object CreateBehavior() 
    { 
     return this; 
    } 
    #endregion 

    #region IServiceBehavior Implementation 
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 
    } 
    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     for (int i = 0; i < serviceHostBase.ChannelDispatchers.Count; i++) 
     { 
      ChannelDispatcher channelDispatcher = serviceHostBase.ChannelDispatchers[i] as ChannelDispatcher; 
      if (channelDispatcher != null) 
      { 
       foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) 
       { 
        MessageInspector inspector = new MessageInspector(); 
        endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector); 
       } 
      } 
     } 
    } 
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
    } 
    #endregion 
} 

public class MessageInspector : IDispatchMessageInspector 
{ 
    public void BeforeSendReply(ref Message reply, object correlationState) 
    { 
    } 
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     HeaderData headerData = request.Headers.GetHeader<HeaderData>("HeaderData", String.Empty); 

     if(headerData != null) 
     { 
      OperationContext.Current.IncomingMessageProperties.Add("HeaderData", headerData); 
     } 

     return null; 
    } 
} 

最後,不要忘了將其配置在app.config文件(客戶端&服務器端)如下:

<behaviors> 
    <endpointBehaviors> 
    <behavior name="NewBehavior"> 
     <fillHeaderDataBehaviourExtension/> 
    </behavior> 
    </endpointBehaviors> 
</behaviors> 
<bindings> 

您還可以通過WCF配置編輯器添加這些行。要做到這一點,請看this的答案。

重要:請注意,您添加的配置這幾行代碼後得到的應用程序配置錯誤:

enter image description here

不要擔心,您的應用程序將正常運行。這是因爲GAC(全局程序集緩存)文件夾不包含此行爲(因爲它是自定義行爲)。您可以通過手動將此行爲添加到計算機上的GAC文件夾來解決此問題。 但是,此錯誤可能會阻止您更新服務引用。如果你嘗試,你會得到這樣的錯誤信息:

enter image description here

所以註釋掉這一行(<extractHeadersBehaviourExtension/>)(客戶端&服務器端),當您更新服務引用。