Wie rufe ich mit C # eine REST-API auf?

333

Dies ist der Code, den ich bisher habe:

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

        }
    }
}

Das Problem ist, dass ich denke, dass der Ausnahmeblock ausgelöst wird (denn wenn ich den try-catch entferne, erhalte ich eine Serverfehlermeldung (500). Aber ich sehe die Console.Out-Zeilen, die ich in den catch-Block eingefügt habe, nicht.

Meine Konsole:

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).

Ich verwende Visual Studio 2011 Beta und .NET 4.5 Beta.

NullVoxPopuli
quelle
Haben Sie dort auch Haltepunkte gesetzt, um zu sehen, wo genau es explodiert?
NotMe
Dies ist das Ergebnis des Ausgabefensters, aber nicht der Konsole
Serj-Tm
5
MSDN hatte einen ausgezeichneten Artikel zum Erstellen von RESTful-Diensten: msdn.microsoft.com/library/dd203052.aspx ... und RESTful-Clients: msdn.microsoft.com/en-us/magazine/ee309509.aspx
Lynn Crumbling
@ChrisLively was hat das mit IE zu tun? = \ Es explodiert in der request.GetResponse-Zeile.
NullVoxPopuli
@TheLindyHop; Absolut gar nichts. Ich habe falsch verstanden.
NotMe

Antworten:

426

Die ASP.Net-Web-API hat die zuvor erwähnte WCF-Web-API ersetzt.

Ich dachte, ich würde eine aktualisierte Antwort veröffentlichen, da die meisten dieser Antworten von Anfang 2012 stammen. Dieser Thread ist eines der Top-Ergebnisse bei einer Google-Suche nach "Call Restful Service C #".

Derzeit wird von Microsoft empfohlen, die Microsoft ASP.NET-Web-API-Clientbibliotheken zu verwenden, um einen RESTful-Dienst zu nutzen. Dies ist als NuGet-Paket Microsoft.AspNet.WebApi.Client verfügbar. Sie müssen dieses NuGet-Paket zu Ihrer Lösung hinzufügen.

So würde Ihr Beispiel aussehen, wenn es mit der ASP.Net Web API Client Library implementiert wird:

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

Wenn Sie mehrere Anforderungen stellen möchten, sollten Sie Ihre HttpClient-Instanz erneut verwenden. In dieser Frage und ihren Antworten finden Sie weitere Informationen dazu, warum in diesem Fall keine using-Anweisung für die HttpClient-Instanz verwendet wurde: Müssen HttpClient und HttpClientHandler entsorgt werden?

Weitere Informationen, einschließlich anderer Beispiele, finden Sie hier: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client

Dieser Blog-Beitrag kann auch nützlich sein: http://johnnycode.com/2012/02/23/consuming-your-own-asp-net-web-api-rest-service/

Brian Swift
quelle
6
Vielen Dank! Ich musste das WebApi-Client-NuGet-Paket installieren, damit dies für mich funktioniert: Install-Package Microsoft.AspNet.WebApi.Client
Ev.
3
Wenn Sie Ihre REST-Integration verspotten müssen, ist dies trotz der Client-Bibliotheken immer noch nicht einfach. Versuchen Sie RestSharp?
Rob Church
6
Um diese Antwort noch besser zu machen als sie bereits ist, sollten Sie die HttpClient-Deklaration in eine using-Anweisung
Daniel Siebert
7
Es wurde versucht, ReadAsAsync () zu verwenden, aber nicht verwendet. Fehler "HttpContent enthält keine Definition für 'ReadAsAsync' und keine Erweiterungsmethode.
Robert Green MBA
7
@RobertGreenMBA: Um die Erweiterungsmethode zu erhalten ReadAsAsync(), fügen Sie einen Verweis auf hinzu System.Net.Http.Formatting.dll. (Intuitiv, richtig?)
Arin
122

Mein Vorschlag wäre, RestSharp zu verwenden . Sie können REST-Services aufrufen und sie mit sehr wenig Code in POCO-Objekte umwandeln lassen, um die Antwort tatsächlich analysieren zu müssen. Dies löst nicht Ihren speziellen Fehler, sondern beantwortet Ihre allgemeine Frage, wie Sie REST-Services anrufen können. Wenn Sie Ihren Code ändern müssen, um ihn verwenden zu können, sollte sich dies in der Benutzerfreundlichkeit und Robustheit der Zukunft auszahlen. Das sind aber nur meine 2 Cent

Beispiel:

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
quelle
6
RestSharp und JSON.NET sind definitiv der richtige Weg. Ich habe festgestellt, dass das MS-Toolset fehlt und wahrscheinlich fehlschlägt.
cbuteau
2
Eine weitere Abstimmung für RestSharp, da Sie es zum Testen viel, viel einfacher als die WebApi-Client-Bibliotheken verspotten können.
Rob Church
1
Für Mono-Benutzer - RestSharp scheint die System.Net WebRequest-API zu verwenden - die meiner Erfahrung nach nicht so zuverlässig ist wie die .net-Implementierungen. ('zufällig' hängt)
Tom
3
Es wäre schön, ein Beispiel in dieser Antwort zu haben.
Caltor
2
Das Fehlen eines Beispiels macht diesen Beitrag nicht hilfreich!
smac2020
39

Ich bin mir sicher, dass Sie nichts damit zu tun haben, aber wickeln Sie Ihre IDisposableObjekte in usingBlöcke, um eine ordnungsgemäße Entsorgung zu gewährleisten:

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
quelle
4
Gute Antwort, bei der keine zusätzlichen Pakete außerhalb der regulären .NET-Umgebung verwendet werden.
Palswim
@ Jesse C. Slicer ... warum ich Fehler 404 in WebResponse getroffen habe webResponse = request.GetResponse ();
Goh Han
2
Weil die Ressource nicht gefunden wurde? Es gibt viele, VIELE Gründe, einen 404 zu bekommen.
Jesse C. Slicer
1
Dies ist eine großartige Lösung @ JesseC.Slicer. Ich kann diesen Code anwenden, um ein Token abzurufen und es von der Konsole aus anzuzeigen. Haben Sie Tipps, damit ich dieses Token jetzt zur Authentifizierung / Anmeldung verwenden kann? Ich möchte GET zum Abrufen einiger Daten verwenden, kann dies jedoch nur, wenn ich angemeldet bin. Wo kann ich mehr darüber erfahren? Vielen Dank!
Paul Laguna
1
Das hat bei mir funktioniert. Vielen Dank!
Shahriar Rahman Zahin
18

Hier sind einige verschiedene Möglichkeiten zum Aufrufen einer externen API in C # (aktualisiert 2019).

Integrierte Möglichkeiten von .NET:

  • WebRequest & WebClient - ausführliche APIs und die Dokumentation von Microsoft sind nicht sehr einfach zu befolgen
  • HttpClient - .NETs neuestes Kind auf dem Block und viel einfacher zu bedienen als oben.

Kostenlose Open-Source-NuGet-Pakete , die offen gesagt eine viel bessere Entwicklererfahrung bieten als die in .NET integrierten Clients:

  • ServiceStack.Text (1k Github-Sterne, 7m Nuget-Downloads) (*) - schnell, leicht und belastbar.
  • RestSharp (6.000 Github-Sterne, 23 Millionen Nuget-Downloads) (*) - einfacher REST- und HTTP-API-Client
  • Flurl (1,7.000 Github-Sterne, 3 Millionen Nuget-Downloads) (*) - eine fließende, tragbare, testbare HTTP-Client-Bibliothek

Alle oben genannten Pakete bieten eine großartige Entwicklererfahrung (dh eine übersichtliche, einfache API) und sind gut gepflegt.

(*) Stand August 2019

Beispiel: Abrufen eines Todo-Elements von einer Fake Rest-API mithilfe von ServiceStack.Text. Die anderen Bibliotheken haben eine sehr ähnliche Syntax.

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

}

Wenn Sie das obige Beispiel in einer .NET Core Console-App ausführen, wird die folgende Ausgabe erzeugt.

Geben Sie hier die Bildbeschreibung ein

Installieren Sie diese Pakete mit NuGet

Install-Package ServiceStack.Text, or

Install-Package RestSharp, or

Install-Package Flurl.Http
Programmieren mit Mark
quelle
17

Bitte verwenden Sie den folgenden Code für Ihre REST-API-Anfrage

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
quelle
-1: .net ist eine verwaltete Plattform, aber HttpClient ist nicht verwaltet (dh Sie MÜSSEN verwenden, um anzugeben, wann diese nicht verwalteten Zeiger entsorgt werden können). Ohne sie lässt sich Ihr Code nicht auf einige Benutzer skalieren (und ja, das ist wichtig, so wichtig, dass die Sprache ein bestimmtes Schlüsselwort hat, um damit umzugehen).
JCKödel
5
@ JCKödel - Sie sind hier nicht absolut richtig und sollten diesen stackoverflow.com/a/22561368 lesen - HttpClient wurde entwickelt, um für mehrere Anrufe
wiederverwendet zu werden
1
Ja @ JCKödel bitte lesen Sie diesen Artikel stackoverflow.com/questions/15705092/…
Nathan
11

Ich möchte meine Lösung in ASP.NET Core freigeben

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

Um etwas zu posten, benutze so etwas:

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

Beispiel zum Löschen:

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

Beispiel, um eine Liste zu erhalten:

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

Beispiel, um nur eines zu erhalten:

ClaimTerm processedClaimImage = await HttpHelper.Get<ClaimTerm>($"/api/values/{id}");
Raskolnikov
quelle
2
Das ist ein wirklich schönes Stück Code, obwohl Sie httpclient nicht in einem using-Block verwenden sollten. siehe aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Myke Black
9

Update zum Aufrufen einer REST-API bei Verwendung von .NET 4.5 oder .NET Core

Ich würde DalSoft.RestClient vorschlagen (Einschränkung, die ich erstellt habe). Der Grund dafür ist, dass Sie mithilfe der dynamischen Typisierung alles in einem fließenden Aufruf zusammenfassen können, einschließlich Serialisierung / De-Serialisierung. Unten sehen Sie ein funktionierendes PUT-Beispiel:

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
quelle
5

ERHALTEN:

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

POST:

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

Hinweis: Zum Serialisieren und Desirialisieren von JSON habe ich das NewGonsoft.Json NuGet-Paket verwendet.

JerryGoyal
quelle
4

Schauen Sie sich Refit an, um Anrufe zu Restdiensten von .net zu tätigen. Ich fand es sehr einfach zu bedienen: https://github.com/paulcbetts/refit

Refit: Die automatische typsichere REST-Bibliothek für .NET Core, Xamarin und .NET

Refit ist eine Bibliothek, die stark von der Retrofit-Bibliothek von Square inspiriert ist und Ihre REST-API in eine Live-Oberfläche verwandelt:

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
quelle
Wissen Sie, ob Refit Reflexion verwendet, um dies zu erreichen? Ich kann die Informationen nirgendwo finden.
Tfrascaroli
sorry @tfrascaroli Ich bin mir nicht sicher.
Patrick Badley
2

Dies ist ein Beispielcode, der sicher funktioniert. Ich habe einen Tag gebraucht, um eine Reihe von Objekten aus dem Rest-Service zu lesen:

RootObject ist der Typ des Objekts, das ich vom Restdienst lese.

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
quelle
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
quelle
1

Ich habe es auf diese einfache Weise mit Web Api 2.0 gemacht. Sie können UseDefaultCredentials entfernen. Ich habe es für meine eigenen Anwendungsfälle verwendet.

            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
quelle
0

Die hier markierte Antwort schlägt vor, HttpClient direkt zu verwenden und zu entsorgen. Dies mag funktionieren, aber es ist ziemlich einfach, auf Probleme mit HttpClient zu stoßen, wenn Sie es nicht richtig verwenden. Wenn Sie HttpClient verwenden, sollten Sie die Erstellung / Entsorgung von HttpClients besser an eine Bibliothek eines Drittanbieters übergeben, die das Factory-Muster verwendet. RestClient.Net ist eine solche Bibliothek.

Es wird mit einer sehr einfachen HttpClient-Factory geliefert, damit Sie nicht auf das Problem der Socket-Erschöpfung stoßen.

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
}

Die IHttpClientFactory-Implementierung von Microsoft kann jedoch auch für die neuesten und besten Anwendungen verwendet werden:

    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 berücksichtigt Abhängigkeitsinjektion, Verspottung, IoC-Container, Testbarkeit von Einheiten und ist vor allem schnell. Ich habe herumgejagt und der einzige andere Client, der in einer ähnlichen Funktion zu arbeiten scheint, ist Flurl.Http

Melbourne Entwickler
quelle
-2

Der erste Schritt besteht darin, die Hilfsklasse für den http-Client zu erstellen.

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

    }
}

Dann können Sie diese Klasse in Ihrem Code verwenden.

Dies ist ein Beispiel dafür, wie Sie die restliche API ohne Träger mit der obigen Klasse aufrufen.

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

Dies ist ein Beispiel dafür, wie Sie den Rest API nennen können, für den ein Inhaber erforderlich ist.

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

Sie können sich auch auf das folgende Repo beziehen, wenn Sie das Arbeitsbeispiel für die Funktionsweise sehen möchten.

https://github.com/mokh223/callApi

mokh223
quelle