Bagaimana cara melakukan panggilan ke api REST menggunakan C #?


335

Ini adalah kode yang saya miliki sejauh ini:

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

        }
    }
}

Masalahnya adalah saya pikir blok pengecualian sedang dipicu (karena ketika saya menghapus try-catch, saya mendapatkan pesan kesalahan server (500). Tapi saya tidak melihat Console.Out baris saya masukkan ke dalam catch block.

Konsol Saya:

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

Saya menggunakan Visual Studio 2011 Beta, dan .NET 4.5 Beta.


Juga, sudahkah Anda menaruh break point di sana untuk melihat di mana, tepatnya, itu meledak?
NotMe

ini adalah hasil dari jendela output tetapi bukan konsol
Serj-Tm

5
MSDN memiliki artikel yang bagus untuk membangun layanan RESTful : msdn.microsoft.com/library/dd203052.aspx ... dan RESTful klien: msdn.microsoft.com/en-us/magazine/ee309509.aspx
Lynn Crumbling

@ ChrisLively apa hubungannya dengan IE? = \ Ini meledak pada baris request.GetResponse.
NullVoxPopuli

@TheLindyHop; Sama sekali tidak ada. Saya salah membaca.
NotMe

Jawaban:


427

ASP.Net Web API telah menggantikan WCF Web API yang disebutkan sebelumnya.

Saya pikir saya akan mengirim jawaban yang diperbarui karena sebagian besar tanggapan ini berasal dari awal 2012, dan utas ini adalah salah satu hasil teratas ketika melakukan pencarian Google untuk "call restful service c #".

Pedoman saat ini dari Microsoft adalah dengan menggunakan Perpustakaan Klien API Web ASP.NET Microsoft untuk menggunakan layanan RESTful. Ini tersedia sebagai paket NuGet, Microsoft.AspNet.WebApi.Client. Anda perlu menambahkan paket NuGet ini ke solusi Anda.

Beginilah contoh Anda akan terlihat ketika diimplementasikan menggunakan Perpustakaan Klien 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();
        }
    }
}

Jika Anda berencana membuat beberapa permintaan, Anda harus menggunakan kembali contoh HttpClient Anda. Lihat pertanyaan ini dan jawabannya untuk perincian lebih lanjut tentang mengapa pernyataan menggunakan tidak digunakan pada contoh HttpClient dalam kasus ini: Apakah HttpClient dan HttpClientHandler harus dibuang?

Untuk detail lebih lanjut, termasuk contoh-contoh lain, buka di sini: http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client

Posting blog ini mungkin juga berguna: http://johnnycode.com/2012/02/23/consuming-your-own-asp-net-web-api-rest-service/


6
Terima kasih! Saya perlu menginstal paket NuGet klien WebApi agar ini berfungsi bagi saya: Instal-Paket Microsoft.AspNet.WebApi.Client
Ev.

3
Jika Anda perlu mengejek integrasi REST Anda, bahkan dengan perpustakaan klien itu masih tidak mudah. Coba RestSharp?
Rob Church

6
Untuk membuat jawaban ini lebih baik daripada yang sudah ada, Anda harus membungkus deklarasi HttpClient menjadi pernyataan menggunakan untuk mengelola sumber daya Anda dengan lebih baik :)
Daniel Siebert

7
Mencoba menggunakan tetapi tidak dapat menggunakan ReadAsAsync (), mendapatkan kesalahan "HttpContent tidak mengandung definisi untuk 'ReadAsAsync' dan tidak ada metode ekstensi.
Robert Green MBA

7
@RobertGreenMBA: Untuk mendapatkan metode ekstensi ReadAsAsync(), tambahkan referensi ke System.Net.Http.Formatting.dll. (Intuitif, kan?)
Arin

122

Saran saya adalah menggunakan RestSharp . Anda dapat membuat panggilan ke layanan REST dan meminta mereka untuk memasukkan objek POCO dengan kode boilerplate yang sangat sedikit untuk benar-benar harus menguraikan respons. Ini tidak akan menyelesaikan kesalahan khusus Anda, tetapi menjawab pertanyaan Anda secara keseluruhan tentang bagaimana melakukan panggilan ke layanan REST. Harus mengubah kode Anda untuk menggunakannya harus membayar dalam kemudahan penggunaan dan ketahanan bergerak maju. Itu hanya 2 sen saya sekalipun

Contoh:

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

6
RestSharp dan JSON.NET jelas merupakan cara yang harus dilakukan. Saya menemukan toolset MS kurang dan cenderung gagal.
cbuteau

2
Pilihan lain untuk RestSharp karena Anda dapat mengejeknya untuk menguji banyak, jauh lebih mudah daripada pustaka Klien WebApi.
Rob Church

1
untuk pengguna mono - RestSharp tampaknya menggunakan apis SystemReNet WebRequest - yang, dalam pengalaman saya tidak dapat diandalkan seperti implementasi .net. ('acak' hang)
Tom

3
Akan menyenangkan untuk memiliki contoh dalam jawaban ini.
Caltor

2
Kurangnya contoh membuat posting ini tidak membantu!
smac2020

39

Tidak terkait, saya yakin, tetapi bungkus IDisposablebenda Anda dalam usingbalok untuk memastikan pembuangan yang benar:

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

        }
    }
}

4
Jawaban bagus yang tidak menggunakan paket tambahan apa pun di luar lingkungan .NET biasa.
palswim

@Jesse C. Slicer..mengapa saya mendapatkan error 404 di WebResponse webResponse = request.GetResponse ();
Goh Han

2
Karena sumber daya itu tidak ditemukan? Ada banyak, BANYAK alasan untuk mendapatkan 404.
Jesse C. Slicer

1
Ini adalah solusi hebat @ JesseC.Slicer. Saya dapat menerapkan kode ini untuk menarik token dan melihatnya dari konsol. Apakah Anda memiliki tips agar saya sekarang mengambil token ini untuk digunakan untuk otentikasi / login? Saya ingin menggunakan GET untuk menarik beberapa data, tetapi hanya bisa jika saya login. Di mana saya bisa belajar lebih banyak tentang ini? Terima kasih!
Paul Laguna

18

Berikut adalah beberapa cara berbeda memanggil API eksternal di C # (diperbarui 2019).

Cara-cara bawaan .NET:

  • WebRequest & WebClient - API verbose & dokumentasi Microsoft tidak mudah diikuti
  • HttpClient - .NET anak terbaru di blok & jauh lebih mudah digunakan daripada di atas.

Paket NuGet sumber terbuka gratis , yang sejujurnya memiliki pengalaman pengembang yang jauh lebih baik daripada .NET yang dibangun di klien:

  • ServiceStack.Text (bintang 1k github, unduhan Nugm 7m) (*) - cepat, ringan, dan tangguh.
  • RestSharp (bintang 6k github, 23m Unduhan Nuget) (*) - REST sederhana dan HTTP API Client
  • Flurl (bintang 1,7 g gubub, Unduhan Nuget 3 m) (*) - pustaka klien HTTP yang lancar, mudah diuji, dan dapat diuji

Semua paket di atas memberikan pengalaman pengembang yang hebat (yaitu API ringkas, mudah) dan dirawat dengan baik.

(*) pada Agustus 2019

Contoh: Mendapatkan item Todo dari API Pemulihan Palsu menggunakan ServiceStack.Text. Perpustakaan lain memiliki sintaks yang sangat mirip.

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

}

Menjalankan contoh di atas dalam aplikasi .NET Core Console, menghasilkan output berikut.

masukkan deskripsi gambar di sini

Instal paket-paket ini menggunakan NuGet

Install-Package ServiceStack.Text, or

Install-Package RestSharp, or

Install-Package Flurl.Http

17

Silakan gunakan kode di bawah ini untuk permintaan api REST Anda

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

-1: .net adalah platform terkelola, tetapi HttpClient tidak dikelola (artinya Anda HARUS menggunakan menggunakan untuk memberi tahu kapan itu dapat membuang pointer yang tidak dikelola). Tanpanya, kode Anda tidak akan menskala ke beberapa pengguna (dan, ya, ini SANGAT penting, sangat penting sehingga bahasa tersebut memiliki kata kunci spesifik untuk menghadapinya).
JCKödel

5
@ JCKödel - Anda tidak sepenuhnya di sini dan harus membaca stackoverflow.com/a/22561368 ini - HttpClient telah dirancang untuk digunakan kembali untuk beberapa panggilan
hB0

1
Ya @ JCKödel silakan baca artikel ini stackoverflow.com/questions/15705092/...
Nathan

11

Saya ingin membagikan solusi saya di 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();
            }
        }
    }
}

Untuk memposting gunakan sesuatu seperti ini:

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

Contoh untuk dihapus:

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

Contoh untuk mendapatkan daftar:

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

Contoh untuk mendapatkan hanya satu:

ClaimTerm processedClaimImage = await HttpHelper.Get<ClaimTerm>($"/api/values/{id}");

2
Itu kode yang benar-benar bagus, walaupun Anda seharusnya tidak menggunakan httpclient di dalam blok use. lihat aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Myke Black

9

Pembaruan untuk memanggil REST API saat menggunakan .NET 4.5 atau .NET Core

Saya akan menyarankan DalSoft.RestClient (peringatan saya membuatnya). Alasannya adalah karena menggunakan pengetikan dinamis Anda dapat membungkus semuanya dalam satu panggilan lancar termasuk serialisasi / de-serialisasi. Di bawah ini adalah contoh PUT yang berfungsi:

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

5

DAPATKAN:

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

POS:

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

Catatan: Untuk membuat serial dan mendesignasi JSON, saya menggunakan paket Newtonsoft.Json NuGet.


4

Lihat Refit untuk melakukan panggilan ke layanan lain dari .net. Saya merasa sangat mudah digunakan: https://github.com/paulcbetts/refit

Reparasi: Pustaka REST aman jenis otomatis untuk .NET Core, Xamarin dan .NET

Refit adalah pustaka yang sangat terinspirasi oleh pustaka Retrofit Square, dan mengubah REST API Anda menjadi antarmuka langsung:

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

Apakah Anda tahu jika Refit menggunakan refleksi untuk mencapai ini? Saya tidak dapat menemukan informasi di mana pun.
tfrascaroli

maaf @ tfrascaroli saya tidak yakin.
patrickbadley

2

Ini adalah contoh kode yang pasti berfungsi. Butuh satu hari untuk membuat ini untuk membaca satu set objek dari layanan Istirahat:

RootObject adalah jenis objek yang saya baca dari layanan lainnya.

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

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

1

Saya melakukannya dengan cara sederhana ini, dengan web Api 2.0. Anda dapat menghapus UseDefaultCredentials.I menggunakannya untuk kasus penggunaan saya sendiri.

            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 ;


0

Jawaban yang ditandai di sini menyarankan menggunakan HttpClient secara langsung dan membuangnya. Ini mungkin berhasil, tetapi cukup mudah untuk mengalami masalah dengan HttpClient jika Anda tidak menggunakannya dengan benar. Jika Anda akan menggunakan HttpClient, lebih baik Anda menyerahkan pembuatan / pembuangan HttpClients ke perpustakaan pihak ke-3 yang menggunakan pola pabrik. RestClient.Net adalah salah satu pustaka tersebut.

Muncul dengan pabrik HttpClient yang sangat dasar sehingga Anda tidak mengalami masalah soket habis,

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
}

Tetapi implementasi IHttpClientFactory dari Microsoft juga dapat digunakan untuk yang terbaru dan terbaik:

    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 memperhitungkan injeksi ketergantungan akun, ejekan, wadah IoC, unit testabilitas, dan yang terpenting adalah cepat. Saya sudah mencari-cari dan satu-satunya klien lain yang tampaknya bekerja dalam kapasitas yang sama adalah Flurl.Http


-2

Langkah pertama adalah membuat kelas pembantu untuk klien 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;
        }

    }
}

Kemudian Anda dapat menggunakan kelas ini dalam kode Anda.

ini adalah contoh bagaimana Anda memanggil api sisanya tanpa pembawa menggunakan kelas di atas.

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

ini contoh bagaimana Anda dapat memanggil api sisanya yang membutuhkan pembawa.

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

Anda juga dapat merujuk ke repo di bawah ini jika Anda ingin melihat contoh kerja tentang cara kerjanya.

https://github.com/mokh223/callApi

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.