Comment puis-je appeler une API REST à l'aide de C #?

335

Voici le code que j'ai jusqu'à présent:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Net.Http;
using System.Web;
using System.Net;
using System.IO;

namespace ConsoleProgram
{
    public class Class1
    {
        private const string URL = "https://sub.domain.com/objects.json?api_key=123";
        private const string DATA = @"{""object"":{""name"":""Name""}}";

        static void Main(string[] args)
        {
            Class1.CreateObject();
        }

        private static void CreateObject()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            request.Method = "POST";
            request.ContentType = "application/json"; 
            request.ContentLength = DATA.Length;
            StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
            requestWriter.Write(DATA);
            requestWriter.Close();

             try {
                WebResponse webResponse = request.GetResponse();
                Stream webStream = webResponse.GetResponseStream();
                StreamReader responseReader = new StreamReader(webStream);
                string response = responseReader.ReadToEnd();
                Console.Out.WriteLine(response);
                responseReader.Close();
            } catch (Exception e) {
                Console.Out.WriteLine("-----------------");
                Console.Out.WriteLine(e.Message);
            }

        }
    }
}

Le problème est que je pense que le bloc d'exception est déclenché (parce que lorsque je supprime le try-catch, j'obtiens un message d'erreur de serveur (500). Mais je ne vois pas la console.

Ma console:

The thread 'vshost.NotifyLoad' (0x1a20) has exited with code 0 (0x0).
The thread '<No Name>' (0x1988) has exited with code 0 (0x0).
The thread 'vshost.LoadReference' (0x1710) has exited with code 0 (0x0).
'ConsoleApplication1.vshost.exe' (Managed (v4.0.30319)): Loaded 'c:\users\l. preston sego iii\documents\visual studio 11\Projects\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe', Symbols loaded.
'ConsoleApplication1.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Configuration\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Configuration.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
A first chance exception of type 'System.Net.WebException' occurred in System.dll
The thread 'vshost.RunParkingWindow' (0x184c) has exited with code 0 (0x0).
The thread '<No Name>' (0x1810) has exited with code 0 (0x0).
The program '[2780] ConsoleApplication1.vshost.exe: Program Trace' has exited with code 0 (0x0).
The program '[2780] ConsoleApplication1.vshost.exe: Managed (v4.0.30319)' has exited with code 0 (0x0).

J'utilise Visual Studio 2011 Beta et .NET 4.5 Beta.

NullVoxPopuli
la source
De plus, avez-vous mis des points d'arrêt là pour voir où, exactement, il explose?
NotMe
c'est le résultat de la fenêtre de sortie mais pas de la console
Serj-Tm
5
MSDN avait un excellent article sur la création de services RESTful: msdn.microsoft.com/library/dd203052.aspx ... et les clients RESTful: msdn.microsoft.com/en-us/magazine/ee309509.aspx
Lynn Crumbling
@ChrisLively qu'est-ce que cela a à voir avec IE? = \ Il explose sur la ligne request.GetResponse.
NullVoxPopuli
@TheLindyHop; Absolument rien. J'ai mal lu.
2012

Réponses:

427

L'API Web ASP.Net a remplacé l'API Web WCF mentionnée précédemment.

Je pensais que je publierais une réponse mise à jour car la plupart de ces réponses datent du début de 2012, et ce fil est l'un des meilleurs résultats lorsque vous effectuez une recherche Google pour "appeler le service reposant c #".

Les conseils actuels de Microsoft consistent à utiliser les bibliothèques clientes de l'API Web Microsoft ASP.NET pour consommer un service RESTful. Il est disponible en tant que package NuGet, Microsoft.AspNet.WebApi.Client. Vous devrez ajouter ce package NuGet à votre solution.

Voici à quoi ressemblerait votre exemple lorsqu'il serait implémenté à l'aide de la bibliothèque cliente de l'API Web ASP.Net:

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers; 

namespace ConsoleProgram
{
    public class DataObject
    {
        public string Name { get; set; }
    }

    public class Class1
    {
        private const string URL = "https://sub.domain.com/objects.json";
        private string urlParameters = "?api_key=123";

        static void Main(string[] args)
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(URL);

            // Add an Accept header for JSON format.
            client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

            // List data response.
            HttpResponseMessage response = client.GetAsync(urlParameters).Result;  // Blocking call! Program will wait here until a response is received or a timeout occurs.
            if (response.IsSuccessStatusCode)
            {
                // Parse the response body.
                var dataObjects = response.Content.ReadAsAsync<IEnumerable<DataObject>>().Result;  //Make sure to add a reference to System.Net.Http.Formatting.dll
                foreach (var d in dataObjects)
                {
                    Console.WriteLine("{0}", d.Name);
                }
            }
            else
            {
                Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
            }

            //Make any other calls using HttpClient here.

            //Dispose once all HttpClient calls are complete. This is not necessary if the containing object will be disposed of; for example in this case the HttpClient instance will be disposed automatically when the application terminates so the following call is superfluous.
            client.Dispose();
        }
    }
}

Si vous prévoyez d'effectuer plusieurs demandes, vous devez réutiliser votre instance HttpClient. Voir cette question et ses réponses pour plus de détails sur les raisons pour lesquelles une instruction using n'a pas été utilisée sur l'instance HttpClient dans ce cas: HttpClient et HttpClientHandler doivent-ils être supprimés?

Pour plus de détails, y compris d'autres exemples, allez ici: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client

Cet article de blog peut également être utile: http://johnnycode.com/2012/02/23/consuming-your-own-asp-net-web-api-rest-service/

Brian Swift
la source
6
Merci! J'avais besoin d'installer le package NuGet du client WebApi pour que cela fonctionne pour moi: Install-Package Microsoft.AspNet.WebApi.Client
Ev.
3
Si vous devez simuler votre intégration REST, même avec les bibliothèques clientes, ce n'est toujours pas facile. Essayez RestSharp?
Rob Church
6
Pour rendre cette réponse encore meilleure qu'elle ne l'est déjà, vous devez encapsuler la déclaration HttpClient dans une instruction using pour mieux gérer votre ressource :)
Daniel Siebert
7
J'ai essayé d'utiliser mais impossible d'utiliser ReadAsAsync (), obtenant l'erreur "HttpContent ne contient pas de définition pour 'ReadAsAsync' et aucune méthode d'extension.
Robert Green MBA
7
@RobertGreenMBA: pour obtenir la méthode d'extension ReadAsAsync(), ajoutez une référence à System.Net.Http.Formatting.dll. (Intuitif, non?)
Arin
122

Ma suggestion serait d'utiliser RestSharp . Vous pouvez appeler des services REST et les faire transtyper en objets POCO avec très peu de code passe-partout pour avoir à analyser la réponse. Cela ne résoudra pas votre erreur particulière, mais répond à votre question générale sur la façon d'appeler les services REST. Devoir changer votre code pour l'utiliser devrait être payant dans la facilité d'utilisation et la robustesse à l'avenir. C'est juste mes 2 cents cependant

Exemple:

namespace RestSharpThingy
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Reflection;

    using RestSharp;

    public static class Program
    {
        public static void Main()
        {
            Uri baseUrl = new Uri("https://httpbin.org/");
            IRestClient client = new RestClient(baseUrl);
            IRestRequest request = new RestRequest("get", Method.GET) { Credentials = new NetworkCredential("testUser", "P455w0rd") };

            request.AddHeader("Authorization", "Bearer qaPmk9Vw8o7r7UOiX-3b-8Z_6r3w0Iu2pecwJ3x7CngjPp2fN3c61Q_5VU3y0rc-vPpkTKuaOI2eRs3bMyA5ucKKzY1thMFoM0wjnReEYeMGyq3JfZ-OIko1if3NmIj79ZSpNotLL2734ts2jGBjw8-uUgKet7jQAaq-qf5aIDwzUo0bnGosEj_UkFxiJKXPPlF2L4iNJSlBqRYrhw08RK1SzB4tf18Airb80WVy1Kewx2NGq5zCC-SCzvJW-mlOtjIDBAQ5intqaRkwRaSyjJ_MagxJF_CLc4BNUYC3hC2ejQDoTE6HYMWMcg0mbyWghMFpOw3gqyfAGjr6LPJcIly__aJ5__iyt-BTkOnMpDAZLTjzx4qDHMPWeND-TlzKWXjVb5yMv5Q6Jg6UmETWbuxyTdvGTJFzanUg1HWzPr7gSs6GLEv9VDTMiC8a5sNcGyLcHBIJo8mErrZrIssHvbT8ZUPWtyJaujKvdgazqsrad9CO3iRsZWQJ3lpvdQwucCsyjoRVoj_mXYhz3JK3wfOjLff16Gy1NLbj4gmOhBBRb8rJnUXnP7rBHs00FAk59BIpKLIPIyMgYBApDCut8V55AgXtGs4MgFFiJKbuaKxq8cdMYEVBTzDJ-S1IR5d6eiTGusD5aFlUkAs9NV_nFw");
            request.AddParameter("clientId", 123);

            IRestResponse<RootObject> response = client.Execute<RootObject>(request);

            if (response.IsSuccessful)
            {
                response.Data.Write();
            }
            else
            {
                Console.WriteLine(response.ErrorMessage);
            }

            Console.WriteLine();

            string path = Assembly.GetExecutingAssembly().Location;
            string name = Path.GetFileName(path);

            request = new RestRequest("post", Method.POST);
            request.AddFile(name, File.ReadAllBytes(path), name, "application/octet-stream");
            response = client.Execute<RootObject>(request);
            if (response.IsSuccessful)
            {
                response.Data.Write();
            }
            else
            {
                Console.WriteLine(response.ErrorMessage);
            }

            Console.ReadLine();
        }

        private static void Write(this RootObject rootObject)
        {
            Console.WriteLine("clientId: " + rootObject.args.clientId);
            Console.WriteLine("Accept: " + rootObject.headers.Accept);
            Console.WriteLine("AcceptEncoding: " + rootObject.headers.AcceptEncoding);
            Console.WriteLine("AcceptLanguage: " + rootObject.headers.AcceptLanguage);
            Console.WriteLine("Authorization: " + rootObject.headers.Authorization);
            Console.WriteLine("Connection: " + rootObject.headers.Connection);
            Console.WriteLine("Dnt: " + rootObject.headers.Dnt);
            Console.WriteLine("Host: " + rootObject.headers.Host);
            Console.WriteLine("Origin: " + rootObject.headers.Origin);
            Console.WriteLine("Referer: " + rootObject.headers.Referer);
            Console.WriteLine("UserAgent: " + rootObject.headers.UserAgent);
            Console.WriteLine("origin: " + rootObject.origin);
            Console.WriteLine("url: " + rootObject.url);
            Console.WriteLine("data: " + rootObject.data);
            Console.WriteLine("files: ");
            foreach (KeyValuePair<string, string> kvp in rootObject.files ?? Enumerable.Empty<KeyValuePair<string, string>>())
            {
                Console.WriteLine("\t" + kvp.Key + ": " + kvp.Value);
            }
        }
    }

    public class Args
    {
        public string clientId { get; set; }
    }

    public class Headers
    {
        public string Accept { get; set; }

        public string AcceptEncoding { get; set; }

        public string AcceptLanguage { get; set; }

        public string Authorization { get; set; }

        public string Connection { get; set; }

        public string Dnt { get; set; }

        public string Host { get; set; }

        public string Origin { get; set; }

        public string Referer { get; set; }

        public string UserAgent { get; set; }
    }

    public class RootObject
    {
        public Args args { get; set; }

        public Headers headers { get; set; }

        public string origin { get; set; }

        public string url { get; set; }

        public string data { get; set; }

        public Dictionary<string, string> files { get; set; }
    }
}
Justin Pihony
la source
6
RestSharp et JSON.NET sont définitivement la voie à suivre. J'ai trouvé que le jeu d'outils MS manquait et risquait d'échouer.
cbuteau
2
Un autre vote pour RestSharp parce que vous pouvez le simuler pour tester beaucoup, beaucoup plus facilement que les bibliothèques WebApi Client.
Rob Church
1
pour les utilisateurs mono - RestSharp semble utiliser les API System.Net WebRequest - qui, selon mon expérience, ne sont pas aussi fiables que les implémentations .net. ('random' se bloque)
Tom
3
Ce serait bien d'avoir un exemple dans cette réponse s'il vous plaît.
Caltor
2
Un manque d'exemple rend ce post inutile!
smac2020
39

Indépendant, j'en suis sûr, mais enveloppez vos IDisposableobjets dans des usingblocs pour assurer une élimination appropriée:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System;
using System.Web;
using System.Net;
using System.IO;

namespace ConsoleProgram
{
    public class Class1
    {
        private const string URL = "https://sub.domain.com/objects.json?api_key=123";
        private const string DATA = @"{""object"":{""name"":""Name""}}";

        static void Main(string[] args)
        {
            Class1.CreateObject();
        }

        private static void CreateObject()
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
            request.Method = "POST";
            request.ContentType = "application/json";
            request.ContentLength = DATA.Length;
            using (Stream webStream = request.GetRequestStream())
            using (StreamWriter requestWriter = new StreamWriter(webStream, System.Text.Encoding.ASCII))
            {
                requestWriter.Write(DATA);
            }

            try
            {
                WebResponse webResponse = request.GetResponse();
                using (Stream webStream = webResponse.GetResponseStream() ?? Stream.Null)
                using (StreamReader responseReader = new StreamReader(webStream))
                {
                    string response = responseReader.ReadToEnd();
                    Console.Out.WriteLine(response);
                }
            }
            catch (Exception e)
            {
                Console.Out.WriteLine("-----------------");
                Console.Out.WriteLine(e.Message);
            }

        }
    }
}
Jesse C. Slicer
la source
4
Belle réponse qui n'utilise aucun package supplémentaire en dehors de l'environnement .NET normal.
palswim
@Jesse C. Slicer..pourquoi j'ai frappé l'erreur 404 dans WebResponse webResponse = request.GetResponse ();
Goh Han
2
Parce que la ressource n'a pas été trouvée? Il y a beaucoup, BEAUCOUP de raisons d'obtenir un 404.
Jesse C. Slicer
1
Ceci est une excellente solution @ JesseC.Slicer. Je peux appliquer ce code pour extraire un jeton et le voir depuis la console. Avez-vous des conseils pour que je prenne maintenant ce jeton à utiliser pour l'authentification / connexion? Je souhaite utiliser GET pour extraire certaines données, mais uniquement si je suis connecté. Où puis-je en savoir plus à ce sujet? Merci!
Paul Laguna
18

Voici quelques façons différentes d'appeler une API externe en C # (mise à jour 2019).

Les moyens intégrés de .NET:

  • WebRequest & WebClient - Les API détaillées et la documentation de Microsoft ne sont pas très faciles à suivre
  • HttpClient - le plus récent enfant de .NET sur le bloc et beaucoup plus simple à utiliser que ci-dessus.

Packages NuGet gratuits et open source , qui ont franchement une bien meilleure expérience de développeur que les clients intégrés de .NET:

  • ServiceStack.Text (1 000 étoiles github, 7 millions de téléchargements Nuget) (*) - rapide, léger et résistant.
  • RestSharp (étoiles github 6k, téléchargements Nuget 23m) (*) - Client API REST et HTTP simple
  • Flurl (1.7k github stars, 3m Nuget Downloads) (*) - une bibliothèque client HTTP fluide, portable et testable

Tous les packages ci-dessus offrent une excellente expérience de développeur (c'est-à-dire une API concise et facile) et sont bien entretenus.

(*) en août 2019

Exemple: Obtention d'un élément Todo à partir d'une API Fake Rest à l'aide de ServiceStack.Text. Les autres bibliothèques ont une syntaxe très similaire.

class Program
{
    static void Main(string[] args)
    {
        // fake rest API
        string url = "https://jsonplaceholder.typicode.com/todos/1";

        // GET data from api & map to Poco
        var todo =  url.GetJsonFromUrl().FromJson<Todo>();

        // print result to screen
        todo.PrintDump();
    }
    public class Todo
    {
        public int UserId { get; set; }
        public int Id { get; set; }
        public string Title { get; set; }
        public bool Completed { get; set; }
    }

}

L'exécution de l'exemple ci-dessus dans une application .NET Core Console produit la sortie suivante.

entrez la description de l'image ici

Installez ces packages à l'aide de NuGet

Install-Package ServiceStack.Text, or

Install-Package RestSharp, or

Install-Package Flurl.Http
Programmation avec Mark
la source
17

Veuillez utiliser le code ci-dessous pour votre demande d'api REST

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Json;

namespace ConsoleApplication2
{
    class Program
    {
        private const string URL = "https://XXXX/rest/api/2/component";
        private const string DATA = @"{
    ""name"": ""Component 2"",
    ""description"": ""This is a JIRA component"",
    ""leadUserName"": ""xx"",
    ""assigneeType"": ""PROJECT_LEAD"",
    ""isAssigneeTypeValid"": false,
    ""project"": ""TP""}";

        static void Main(string[] args)
        {
            AddComponent();
        }

        private static void AddComponent()
        {
            System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
            client.BaseAddress = new System.Uri(URL);
            byte[] cred = UTF8Encoding.UTF8.GetBytes("username:password");
            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(cred));
            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

            System.Net.Http.HttpContent content = new StringContent(DATA, UTF8Encoding.UTF8, "application/json");
            HttpResponseMessage messge = client.PostAsync(URL, content).Result;
            string description = string.Empty;
            if (messge.IsSuccessStatusCode)
            {
                string result = messge.Content.ReadAsStringAsync().Result;
                description = result;
            }
        }
    }
}
Srinivasan Radhakrishnan
la source
-1: .net est une plate-forme gérée, mais HttpClient n'est pas géré (ce qui signifie que vous DEVEZ utiliser l'utilisation pour lui dire quand il peut supprimer ces pointeurs non gérés). Sans cela, votre code ne s'adaptera pas à quelques utilisateurs (et, oui, c'est important, si important que la langue ait un mot-clé spécifique pour y faire face).
JCKödel
5
@ JCKödel - Vous n'êtes pas absolument ici et vous devriez lire ce stackoverflow.com/a/22561368 - HttpClient a été conçu pour être réutilisé pour plusieurs appels
hB0
1
Oui @ JCKödel s'il vous plaît lire cet article stackoverflow.com/questions/15705092/…
Nathan
11

Je souhaite partager ma solution dans ASP.NET Core

using Newtonsoft.Json;
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;

namespace WebApp
{
    public static class HttpHelper
    {
        // In my case this is https://localhost:44366/
        private static readonly string apiBasicUri = ConfigurationManager.AppSettings["apiBasicUri"];

        public static async Task Post<T>(string url, T contentValue)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(apiBasicUri);
                var content = new StringContent(JsonConvert.SerializeObject(contentValue), Encoding.UTF8, "application/json");
                var result = await client.PostAsync(url, content);
                result.EnsureSuccessStatusCode();
            }
        }

        public static async Task Put<T>(string url, T stringValue)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(apiBasicUri);
                var content = new StringContent(JsonConvert.SerializeObject(stringValue), Encoding.UTF8, "application/json");
                var result = await client.PutAsync(url, content);
                result.EnsureSuccessStatusCode();
            }
        }

        public static async Task<T> Get<T>(string url)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(apiBasicUri);
                var result = await client.GetAsync(url);
                result.EnsureSuccessStatusCode();
                string resultContentString = await result.Content.ReadAsStringAsync();
                T resultContent = JsonConvert.DeserializeObject<T>(resultContentString);
                return resultContent;
            }
        }

        public static async Task Delete(string url)
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri(apiBasicUri);
                var result = await client.DeleteAsync(url);
                result.EnsureSuccessStatusCode();
            }
        }
    }
}

Pour publier, utilisez quelque chose comme ceci:

await HttpHelper.Post<Setting>($"/api/values/{id}", setting);

Exemple de suppression:

await HttpHelper.Delete($"/api/values/{id}");

Exemple pour obtenir la liste:

List<ClaimTerm> claimTerms = await HttpHelper.Get<List<ClaimTerm>>("/api/values/");

Exemple pour en obtenir un seul:

ClaimTerm processedClaimImage = await HttpHelper.Get<ClaimTerm>($"/api/values/{id}");
Raskolnikov
la source
2
C'est un très bon morceau de code, bien que vous ne devriez pas utiliser httpclient dans un bloc using. voir aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Myke Black
9

Mise à jour pour appeler une API REST lors de l'utilisation de .NET 4.5 ou .NET Core

Je suggère DalSoft.RestClient (mise en garde, je l'ai créé). La raison étant qu'il utilise la saisie dynamique, vous pouvez tout terminer en un seul appel fluide, y compris la sérialisation / désérialisation. Voici un exemple de PUT fonctionnel:

dynamic client = new RestClient("http://jsonplaceholder.typicode.com");

var post = new Post { title = "foo", body = "bar", userId = 10 };

var result = await client.Posts(1).Put(post);
DalSoft
la source
5

AVOIR:

// GET JSON Response
public WeatherResponseModel GET(string url) {
    WeatherResponseModel model = new WeatherResponseModel();
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    try {
        WebResponse response = request.GetResponse();
        using(Stream responseStream = response.GetResponseStream()) {
            StreamReader reader = new StreamReader(responseStream, Encoding.UTF8);
            model = JsonConvert.DeserializeObject < WeatherResponseModel > (reader.ReadToEnd());
        }
    } catch (WebException ex) {
        WebResponse errorResponse = ex.Response;
        using(Stream responseStream = errorResponse.GetResponseStream()) {
            StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
            String errorText = reader.ReadToEnd();
            // log errorText
        }
        throw;
    }

    return model;
}

PUBLIER:

// POST a JSON string
void POST(string url, string jsonContent) {
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "POST";

    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    Byte[]byteArray = encoding.GetBytes(jsonContent);

    request.ContentLength = byteArray.Length;
    request.ContentType =  @ "application/json";

    using(Stream dataStream = request.GetRequestStream()) {
        dataStream.Write(byteArray, 0, byteArray.Length);
    }
    long length = 0;
    try {
        using(HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
            // got response
            length = response.ContentLength;
        }
    } catch (WebException ex) {
        WebResponse errorResponse = ex.Response;
        using(Stream responseStream = errorResponse.GetResponseStream()) {
            StreamReader reader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));
            String errorText = reader.ReadToEnd();
            // log errorText
        }
        throw;
    }
}

Remarque: Pour sérialiser et désirer JSON, j'ai utilisé le package Newtonsoft.Json NuGet.

JerryGoyal
la source
4

Consultez Refit pour passer des appels aux services de repos à partir de .net. Je l'ai trouvé très facile à utiliser: https://github.com/paulcbetts/refit

Refit: la bibliothèque REST de type sécurisé automatique pour .NET Core, Xamarin et .NET

Refit est une bibliothèque fortement inspirée de la bibliothèque Retrofit de Square, et elle transforme votre API REST en une interface en direct:

public interface IGitHubApi {
        [Get("/users/{user}")]
        Task<User> GetUser(string user); } The RestService class generates an implementation of IGitHubApi that uses HttpClient to make its calls:

var gitHubApi = RestService.For<IGitHubApi>("https://api.github.com");

var octocat = await gitHubApi.GetUser("octocat");
patrickbadley
la source
Savez-vous si Refit utilise la réflexion pour y parvenir? Je ne trouve l'information nulle part.
tfrascaroli
désolé @tfrascaroli, je ne suis pas sûr.
patrickbadley
2

Ceci est un exemple de code qui fonctionne à coup sûr. Cela m'a pris un jour pour faire ceci pour lire un ensemble d'objets du service Rest:

RootObject est le type de l'objet que Im lit à partir du service de repos.

string url = @"http://restcountries.eu/rest/v1";
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(IEnumerable<RootObject>));
WebClient syncClient = new WebClient();
string content = syncClient.DownloadString(url);

using (MemoryStream memo = new MemoryStream(Encoding.Unicode.GetBytes(content)))
{
    IEnumerable<RootObject> countries = (IEnumerable<RootObject>)serializer.ReadObject(memo);    
}

Console.Read();
user4064093
la source
1
    var TakingRequset = WebRequest.Create("http://xxx.acv.com/MethodName/Get");
    TakingRequset.Method = "POST";
    TakingRequset.ContentType = "text/xml;charset=utf-8";
    TakingRequset.PreAuthenticate = true;

    //---Serving Request path query
     var PAQ = TakingRequset.RequestUri.PathAndQuery;

    //---creating your xml as per the host reqirement
    string xmlroot=@"<root><childnodes>passing parameters</childnodes></root>";
    string xmlroot2=@"<root><childnodes>passing parameters</childnodes></root>";

    //---Adding Headers as requested by host 
    xmlroot2 = (xmlroot2 + "XXX---");
    //---Adding Headers Value as requested by host 
  //  var RequestheaderVales = Method(xmlroot2);

    WebProxy proxy = new WebProxy("XXXXX-----llll", 8080);
    proxy.Credentials = new NetworkCredential("XXX---uuuu", "XXX----", "XXXX----");
    System.Net.WebRequest.DefaultWebProxy = proxy;


    // Adding The Request into Headers
    TakingRequset.Headers.Add("xxx", "Any Request Variable ");
    TakingRequset.Headers.Add("xxx", "Any Request Variable");

    byte[] byteData = Encoding.UTF8.GetBytes(xmlroot);
    TakingRequset.ContentLength = byteData.Length;

    using (Stream postStream = TakingRequset.GetRequestStream())
    {
        postStream.Write(byteData, 0, byteData.Length);
        postStream.Close();
    }



    StreamReader stredr = new StreamReader(TakingRequset.GetResponse().GetResponseStream());
    string response = stredr.ReadToEnd();
rajendra lenka
la source
1

Je l'ai fait de cette manière simple, avec le Web Api 2.0. Vous pouvez supprimer UseDefaultCredentials.Je l'ai utilisé pour mes propres cas d'utilisation.

            List<YourObject> listObjects = new List<YourObject>();


            string response = "";
            using (var client = new WebClient() { UseDefaultCredentials = true })
            {
                 response = client.DownloadString(apiUrl);
            }

            listObjects = JsonConvert.DeserializeObject<List<YourObject>>(response);
            return listObjects ;
MNF
la source
0

La réponse indiquée ici suggère d'utiliser directement HttpClient et de le supprimer. Cela peut fonctionner, mais il est assez facile de rencontrer des problèmes avec HttpClient si vous ne l'utilisez pas correctement. Si vous allez utiliser HttpClient, vous feriez mieux de confier la création / suppression de HttpClients à une bibliothèque tierce qui utilise le modèle d'usine. RestClient.Net est une de ces bibliothèques.

Il est livré avec une usine HttpClient très basique afin que vous ne rencontriez pas le problème d'épuisement de socket,

public class DefaultHttpClientFactory : IHttpClientFactory, IDisposable
{
    #region Fields
    private bool disposed;
    private readonly ConcurrentDictionary<string, Lazy<HttpClient>> _httpClients;
    private readonly Func<string, Lazy<HttpClient>> _createClientFunc;
    #endregion

    #region Constructor
    public DefaultHttpClientFactory() : this(null)
    {
    }

    public DefaultHttpClientFactory(Func<string, Lazy<HttpClient>> createClientFunc)
    {
        _createClientFunc = createClientFunc;
        _httpClients = new ConcurrentDictionary<string, Lazy<HttpClient>>();

        if (_createClientFunc != null) return;
        _createClientFunc = name =>
        {
            return new Lazy<HttpClient>(() => new HttpClient(), LazyThreadSafetyMode.ExecutionAndPublication);
        };
    }
    #endregion

    #region Implementation
    public HttpClient CreateClient(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException(nameof(name));
        }

        return _httpClients.GetOrAdd(name, _createClientFunc).Value;
    }

    public void Dispose()
    {
        if (disposed) return;
        disposed = true;

        foreach (var name in _httpClients.Keys)
        {
            _httpClients[name].Value.Dispose();
        }
    }
    #endregion
}

Mais l'implémentation IHttpClientFactory de Microsoft peut également être utilisée pour la dernière et la meilleure:

    var serviceCollection = new ServiceCollection();
    var baseUri = new Uri("http://www.test.com");
    serviceCollection.AddSingleton(typeof(ISerializationAdapter), typeof(NewtonsoftSerializationAdapter));
    serviceCollection.AddSingleton(typeof(ILogger), typeof(ConsoleLogger));
    serviceCollection.AddSingleton(typeof(IClient), typeof(Client));
    serviceCollection.AddDependencyInjectionMapping();
    serviceCollection.AddTransient<TestHandler>();

    //Make sure the HttpClient is named the same as the Rest Client
    serviceCollection.AddSingleton<IClient>(x => new Client(name: clientName, httpClientFactory: x.GetRequiredService<IHttpClientFactory>()));
    serviceCollection.AddHttpClient(clientName, (c) => { c.BaseAddress = baseUri; })
        .AddHttpMessageHandler<TestHandler>();

    var serviceProvider = serviceCollection.BuildServiceProvider();
    var client = serviceProvider.GetService<IClient>();
    await client.GetAsync<object>();

RestClient.Net prend en compte l'injection de dépendances, la moquerie, les conteneurs IoC, la testabilité des unités, et surtout est rapide. J'ai cherché et le seul autre client qui semble fonctionner à un niveau similaire est Flurl.Http

Développeur Melbourne
la source
-2

La première étape consiste à créer la classe d'assistance pour le client http.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace callApi.Helpers
{
    public class CallApi
    {
        private readonly Uri BaseUrlUri;
        private HttpClient client = new HttpClient();

        public CallApi(string baseUrl)
        {
            BaseUrlUri = new Uri(baseUrl);
            client.BaseAddress = BaseUrlUri;
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));

        }

        public HttpClient getClient()
        {
            return client;
        }

        public HttpClient getClientWithBearer(string token)
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            return client;
        }

    }
}

Ensuite, vous pouvez utiliser cette classe dans votre code.

ceci est un exemple de la façon dont vous appelez l'api de repos sans support en utilisant la classe ci-dessus.

// GET api/values
[HttpGet]
public async Task<ActionResult<string>> postNoBearerAsync(string email, string password,string baseUrl, string action)
{
    var request = new LoginRequest
    {
        email = email,
        password = password
    };

    var callApi = new CallApi(baseUrl);
    var client = callApi.getClient();
    HttpResponseMessage response = await client.PostAsJsonAsync(action, request);
    if (response.IsSuccessStatusCode)
        return Ok(await response.Content.ReadAsAsync<string>());
    else
        return NotFound();
}

c'est un exemple de la façon dont vous pouvez appeler les autres API qui nécessitent un support.

// GET api/values
[HttpGet]
public async Task<ActionResult<string>> getUseBearerAsync(string token, string baseUrl, string action)
{
    var callApi = new CallApi(baseUrl);
    var client = callApi.getClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    HttpResponseMessage response = await client.GetAsync(action);
    if (response.IsSuccessStatusCode)
    {
        return Ok(await response.Content.ReadAsStringAsync());

    }
    else
        return NotFound();
}

vous pouvez également vous référer au dépôt ci-dessous si vous voulez voir l'exemple de fonctionnement de la façon dont cela fonctionne.

https://github.com/mokh223/callApi

mokh223
la source