2012-11-04 17 views
18

che io chiamo un servizio esterno utilizzando HttpClient all'interno di un progetto di Api 4 Web ASP.Net MVC in esecuzione su .Net Framework 4.5Calling servizio HTTP esterno utilizzando HttpClient da un'azione Web API

Il codice di esempio è la seguente (ignorare i valori di ritorno in quanto questo è il codice di esempio per testare chiamare un servizio esterno):

public class ValuesController : ApiController 
{ 
    static string _address = "http://api.worldbank.org/countries?format=json"; 
    private string result; 

    // GET api/values 
    public IEnumerable<string> Get() 
    { 
     GetResponse(); 
     return new string[] { result, "value2" }; 
    } 

    private async void GetResponse() 
    { 
     var client = new HttpClient(); 
     HttpResponseMessage response = await client.GetAsync(_address); 
     response.EnsureSuccessStatusCode(); 
     result = await response.Content.ReadAsStringAsync(); 
    } 
} 

Mentre il codice nel metodo privato effettivamente funziona il problema che ho è che il Get controller() chiama il GetResponse() ma non è in attesa del risultato, ma esegue immediatamente il risultato con result = null.

Ho anche provato ad utilizzare una chiamata sincrona più semplice con un WebClient come segue:

// GET api/values 
    public IEnumerable<string> Get() 
    { 
     //GetResponse(); 

     var client = new WebClient(); 

     result = client.DownloadString(_address); 

     return new string[] { result, "value2" }; 
    } 

che funziona bene.

Cosa sto sbagliando? Perché Get() non attende il completamento del metodo privato nel campione asincrono?

+0

non è necessario richiamare GetResponse() anche con attendere? Altrimenti, questo non aspetterà che il metodo finisca ... e l'azione del controller finirà direttamente lasciando il risultato essere ancora nullo. – jishi

+0

Sì, ma non mi ero reso conto che potevo contrassegnare Get() come asincrono che è necessario per l'attesa. – Redeemed1

risposta

30

Aha, avevo bisogno di fare quanto segue (restituire un compito piuttosto poi void):

// GET api/values 
    public async Task<IEnumerable<string>> Get() 
    { 
     var result = await GetExternalResponse(); 

     return new string[] { result, "value2" }; 
    } 

    private async Task<string> GetExternalResponse() 
    { 
     var client = new HttpClient(); 
     HttpResponseMessage response = await client.GetAsync(_address); 
     response.EnsureSuccessStatusCode(); 
     var result = await response.Content.ReadAsStringAsync(); 
     return result; 
    } 

Anche io non avevo capito che potevo segnare l'operazione Get() come async che è quello che mi ha permesso di attendi la chiamata esterna.

Grazie a Stephen Cleary per il suo post sul blog Async and Await che mi ha indirizzato nella giusta direzione.

+0

Proprio quello che stavo cercando dagli ultimi 3 giorni! Semplice una volta che lo conosci :) La risposta più breve e più efficace. –

0

Con nome utente e password, chiamare Httpclient. In caso di autenticazione richiesta API.

public async Task<ActionResult> Index() 
{ 

      const string uri = "https://testdoamin.zendesk.com/api/v2/users.json?role[]=agent"; 
      using (var client1 = new HttpClient()) 
      { 
       var header = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("[email protected]:123456")));///username:password for auth 
       client1.DefaultRequestHeaders.Authorization = header; 
       var aa = JsonConvert.DeserializeObject<dynamic>(await client1.GetStringAsync(uri)); 

      } 
} 
+0

Karan, grazie per il tuo impegno qui, ma questo non è correlato alla domanda. La tua risposta si riferisce all'autenticazione, la domanda si riferisce ai compiti asincroni su una api non autenticata – Redeemed1

Problemi correlati