2012-11-04 5 views
18

ich einen externen Service nenne wird 4,5Aufruf externen HTTP-Dienstes Httpclient von einer Web-API Aktion mit

Der Beispielcode wie folgt (ignorieren die Rückgabewerte als diese Beispielcode ist ein externer Service zu testen Aufruf):

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(); 
    } 
} 

Während der Code in der privaten Methode in der Tat das Problem, das ich habe nicht funktioniert, ist, dass der Controller Get() die GetResponse() aufruft, aber es wartet nicht auf das Ergebnis, sondern führt sofort die Rückgabe mit result = null aus.

ich auch mit einem WebClient mit einem einfacheren synchronen Aufruf versucht haben, wie folgt:

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

     var client = new WebClient(); 

     result = client.DownloadString(_address); 

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

der gut arbeitet.

Was mache ich falsch? Warum wartet Get() nicht auf die Beendigung der privaten Methode im asynchronen Beispiel?

+0

müssen Sie GetResponse() nicht mit gonna abwarten? Sonst wartet das nicht darauf, dass diese Methode beendet wird ... und Ihre Controller-Aktion beendet das Ergebnis direkt, so dass es immer noch null ist. – jishi

+0

Ja, aber ich hatte nicht erkannt, dass ich die Get() als async markieren konnte, die benötigt wird, um zu warten. – Redeemed1

Antwort

30

Aha, ich brauchte die folgende (Rückkehr eine Aufgabe eher dann void) zu tun:

// 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; 
    } 

Auch hatte ich nicht realisiert werden konnte ich den Get() Betrieb als Asynchron-Marke, die, was mir erlaubt ist, auf den externen Anruf warten.

Danke an Stephen Cleary für seinen Blogpost Async and Await, der mich in die richtige Richtung wies.

+0

Genau das, was ich seit den letzten 3 Tagen gesucht habe! Einfach, sobald Sie es wissen :) Die kürzeste und die effektivste Antwort. –

0

Mit dem Benutzernamen und dem Passwort rufen Sie Httpclient. Im Falle einer API-Authentifizierung erforderlich.

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, danke für deine Mühe hier, aber das hängt nicht mit der Frage zusammen. Ihre Antwort bezieht sich auf die Authentifizierung, die Frage bezieht sich auf Async-Aufgaben um eine nicht authentifizierte API – Redeemed1