2012-10-24 28 views
0

我正在使用HttpClient(又名Web API客戶端)來使用RESTfull服務。 服務需要建立會話(通過登錄),然後在每次操作時銷燬(通過註銷)。因此,消費服務A的調用看起來是這樣的(僞)如何在使用Web API時概括登錄,操作和註銷HttpClient

// setup 
create auth dictionary authDict 
create authenticationContent using FormUrlEndodeContent(authDict) 
create cookieContainer 
create HttpClientHandler... 
create HttpClient 

// login 
await httpClient.PostAsync(LoginUrl, authenticationContent); 
do error checking 

// perform Operation A 
await httpClient.....post...or...get... 
extract data, process it, tranform it, get a cup of coffee, etc, etc 
populate OperationAResult 

// logout 
await httpClient.GetAsync(LogoutUrl); 

// return result 
return OperationAResult 

我的問題是,我怎麼能輕易重用的設置,登錄和註銷針對不同的操作? 我應該創建一些方法,將採取行動<>如果是的話如何確保操作順序發生?

回答

1

可能最簡單的方法就是寫一個包裝類。

public class MyHttpClient 
{ 
    private HttpClient _client = new HttpClient(); 
    private MyHttpClientSetup _setup; 

    public MyHttpClient(MyHttpClientSetup setup) 
    { 
    this._setup = setup; 
    } 

    private void HttpLogin() 
    { 
    // .. custom login stuff that uses this._setup 
    }  

    private void HttpLogout() 
    { 
    // .. custom logout stuff that uses this._setup 
    }  

    public void Reset() 
    { 
    this._client = new HttpClient(); 
    } 

    // Wrapped Properties from the private HttpClient (1 example) 
    public Uri BaseAddress 
    { 
    get{ return this._client.BaseAddress;} 
    set{ this._client.BaseAddress = value;} 
    } 

    // Wrapped HttpMethods (1 example) 
    // Extremely poorly written, should be delegated properly 
    // This is just a bad example not using Task properly 
    public Task<HttpResponseMessage> DeleteAsync(string requestUri) 
    { 
    this.HttpLogin(); 
    Task<HttpResponseMessage> result = this._client.DeleteAsync(requestUri); 
    this.HttpLogout(); 
    return result; 
    } 


    public class MyHttpClientSetup 
    { 
    // Properties required for setup; 
    } 
} 
1

您可以創建一個新的MessageHandler來透明地處理這些東西。

public class ConnectionHandler : DelegatingHandler { 

     public HttpClient HttpClient {get;set;} 

     public TestHandler(HttpMessageHandler handler) { 
      this.InnerHandler = handler; 
     } 
     protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) 
     { 
      // Do your login stuff here 
      return base.SendAsync(request, cancellationToken) // Make your actual request 
       .ContinueWith(t => { 
          // Do your logout stuff here 
          } 
     } 
    } 

然後你可以使用一個HttpClient實例來完成你所有的請求。要將您的處理程序添加到請求/響應管道中,您只需創建一個常規HttpClientHandler,將其分配給DelegatingHandler的InnerHandler屬性,然後將新處理程序傳遞給HttpClient的構造函數。從那時起,通過HttpClient所做的所有請求都將通過您的ConnnectionHandler進行路由。

var connectionHandler = new ConnectionHandler(new HttpClientHandler()); 
    var client = new HttpClient(connectionHandler); 
    connectionHandler.HttpClient = client; 

    var response = client.GetAsync("http://example.org/request").Result; 

使用單個HttpClient實例的優點是您不必保持重新指定DefaultRequestHeaders。另外,配置HttpClient會終止TCP連接,所以下一個請求將不得不重新打開它。

+0

我已經看到這種方法在Codeplex上的HttpClient示例中創建自定義處理程序,它很好。但在同一個「操作」過程中,我需要「擊中」3個不同的URL(登錄,服務,註銷)。在SendAsync覆蓋中,我只有請求,所以必須創建一個單獨的HttpClient實例嗎?這就是我想要避免的...看看BingTranslate的例子,他們做了幾乎類似的方法,其中一個單獨的客戶端用於獲取Azure數據令牌... – zam6ak

+0

...爲了讓事情「更容易」,一旦我打/ login一個cookie被創建(encypted autho),需要被「結轉」到下一個調用(操作)以及/註銷調用(這樣我不會超過最大會話數量)..... – zam6ak

+0

@ zam6ak將HttpClient屬性添加到ConnectionHandler併爲其提供對Httpclient實例的引用。使用相同的HttpClient進行多個同時請求沒有問題。 –