web-dev-qa-db-fra.com

Appel du service HTTP externe à l'aide de HttpClient à partir d'une action API Web

J'appelle un service externe utilisant HttpClient à partir d'un projet Api Web ASP.Net MVC 4 exécuté sur .Net Framework 4.5.

L'exemple de code est le suivant (ignorez les valeurs de retour car il s'agit d'un exemple de code pour tester l'appel d'un service externe):

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

Bien que le code de la méthode privée fonctionne, le problème que j’ai est que le contrôleur Get () appelle GetResponse () mais il n’attend pas le résultat, mais exécute immédiatement le retour avec result = null.

J'ai également essayé d'utiliser un appel synchrone plus simple avec un client Web, comme suit:

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

        var client = new WebClient();

        result = client.DownloadString(_address);

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

qui fonctionne bien.

Qu'est-ce que je fais mal? Pourquoi Get () n'attend-il pas l'achèvement de la méthode privée dans l'exemple asynchrone?

21
Redeemed1

Aha, je devais faire ce qui suit (retourner une tâche plutôt que vide):

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

De plus, je n'avais pas réalisé que je pouvais marquer l'opération Get () comme asynchrone, ce qui m'a permis d'attendre l'appel externe.

Merci à Stephen Cleary pour son article de blog Async and Await qui m'a orienté dans la bonne direction.

34
Redeemed1

Avec le nom d'utilisateur et le mot de passe, appelez Httpclient. En cas d'API, authentification requise.

    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 Singh