0

HttpClient (웹 API 클라이언트라고도 함)을 사용하여 RESTfull 서비스를 사용하고 있습니다. 서비스를 사용하려면 로그인을 통해 세션을 설정 한 다음 각 작업을 수행 할 때 세션을 종료해야합니다 (로그 아웃을 통해). 그래서 서비스 A를 소비 할 수있는 호출이 (의사) 같은웹 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

나는이 접근법을 코드 플렉스의 HttpClient 예제에서 사용자 정의 처리기를 생성하는 것으로 보아왔다. 그러나 동일한 "작업"중에 3 가지 URL (로그인, 서비스, 로그 아웃)에 "노출"해야합니다. SendAsync 오버라이드에서 별도의 HttpClient 인스턴스를 생성해야하므로 요청이있을뿐입니다. 내가 피하려고하는 것입니다 ... BingTranslate 예제를 보면 Azure 데이터 토큰을 얻기 위해 별도의 클라이언트가 사용 된 비슷한 접근 방식을 취했습니다 ... – zam6ak

+0

.../login 다음 호출 (작업)과/logout 호출 ("최대 세션 수"를 초과하지 않도록)에 "이월"되어야하는 쿠키가 생성됩니다 (encypted autho) ..... – zam6ak

+0

@ zam6ak ConnectionHandler에 HttpClient 속성을 추가하고 Httpclient 인스턴스에 대한 참조를 제공합니다. 같은 HttpClient로 여러 개의 동시 요청을하는 데 아무런 문제가 없습니다. –