2011-10-03 24 views
1

我有一個Web服務將被某些應用程序(當前的Web站點)使用。WCF服務調用在每次調用中都包含相同的信息

這些調用幾乎都是特定於某個客戶,但仍然是相同的。所以一個調用可能是getAllFoo(),但我需要一些參數來說明Foo來自哪個客戶端。

如果我只是將一個標準參數添加到所有調用中,它會很快變得很麻煩,所以我希望能夠幹一點DRY和自動。一些可能包含在所有服務調用中的東西。

IDispatchMessageInspector對我來說是正確的嗎?什麼樣的信息可以包括,我可以訪問方法內的信息?

我應該爲呼叫創建某種屬性嗎?

如果任何人都可以指出我的解決方案,這將是偉大的。

編輯

另一種解決方案,我想了。

如果在特定客戶端的服務調用發生在客戶端,那麼它將在instanceCreation中知道,因此我可以使用已知的客戶端實例化ServiceClient。

我可以以某種方式爲ClientBase<>擴展器使用此解決方案。

假設我正在爲Domain1服務(讓我們稱客戶端域不會將其與服務客戶端/客戶端混淆)我創建一個InformationProvider消費者端,它具有ClientBase<IInformationService>字段。我確保DomainName(domain1)被設置爲構建,所以我可以在實例化ClientBase<IInformationService>時做同樣的事情,所以它讓服務知道我要求的域名。

我只是還在學習WCF所以我不知道如何做到這一點。

回答

1

我可以理解,你要保持你的解決方案簡單而整齊,但最終 - 就像你說的自己 -

...我需要一些參數來表示從客戶端...

最明顯和最簡單的解決方案是在需要的所有服務調用中包含client參數。當然會有不需要客戶端參數的服務調用,在這種情況下,您不需要包含參數。

如果客戶端標識符在封面下謹慎傳遞,您可以做一些巧妙的事情,但要小心做不必要的巧妙事情。我將通過客戶端作爲一個簡單的參數,因爲它被用作參數。想到兩個原因:

  1. 如果有人維護您的代碼,他們很快就會明白髮生了什麼事情。
  2. 如果有人需要使用該服務,很明顯如何使用它。
+0

我之前遇到過問題,不做事幹,我真的不想把這個額外的參數都添加到每一個OperationContract,然後再給我做的每一個調用。我將主要維護這些代碼,並創建消耗它的客戶端。感謝您的輸入。 –

+1

我認爲這是正確的做法,但我會給你另一個答案,然後。 –

+0

@ Kirk Hang on sec。我要添加更多信息。 –

1

一個可能的模式:

  • 確保您服務每會話實例。這意味着您不得不使用wsHttpBinding,netTcpBinding或自定義綁定,因爲http不支持會話。
  • 當實例化每個會話時,始終調用一個初始化操作,該操作爲該服務設置客戶端ID。
  • 將此初始化操作放入代理的構造函數中。

涉及的步驟是這樣的:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)] 
public class MyService : IMyService 
{ 
    private int clientId; 

    public void StartUp(int clientId) 
    { 
     this.clientId = clientId; 

,然後客戶端,假設你使用生成的代理,包裹內的客戶端另一個代理。

public class ExtendedClient : MyServiceClient 
{ 
    public ExtendedClient(int clientid) : base() 
    { 
     this.StartUp(clientid); 
    } 

現在您應該實例化ExtendedClient,它將創建通道並通過提供客戶端ID來填充服務。

我個人更喜歡簡單地發送每個服務調用的客戶端ID,但如果您能夠使用會話綁定,那麼這應該工作。


只是一些關於WCF的信息給你。如果您擁有無狀態服務,那麼您需要在每次服務調用中將客戶端作爲參數包含在內。這並不是而是,這意味着您需要在整個代碼中包含客戶端 - 例如,您可以在ClientBase構造函數中檢索它。但是您需要將其添加到每個OperationContract和所有服務實現中。

另一種方法是創建一個有狀態服務 - 您首次使用的實例將保留供您重用(除超時/異常外)。在這種情況下,您可能只需發送一次客戶端,然後服務就會知道客戶端的後續呼叫。這是上面描述的模式。這意味着你不能使用http綁定。我相信通過這樣做,你只會增加應用程序出現問題的可能性(有狀態的服務,必須確保初始化操作完成,進行更多的服務調用)。

+0

我要試一試,看起來不錯。我會打電話給另一個計劃B :) –

+0

我在考慮你在編輯中說的話。我可以把它作爲一個參數,因爲一旦我做其他消費者會更容易。我試圖想到用ClientBase <>做到這一點的一種方法。我想把它設置爲一個字段,並將其添加到Channel.Method(clientId,otherParams)將是可以接受的。有沒有什麼辦法可以在這裏做Genralize方法? –

+0

@IngóVals因爲ClientBase <>是全部生成的代碼,所以改變並不容易。它是作爲一個部分類生成的,所以你可以擴展它,並定義一個替代構造函數來爲你設置客戶端參數。或者,您可以像上面所做的那樣,從ClientBase類擴展到您自己的版本。 –