Melakukan panggilan cURL di C #

89

Saya ingin melakukan curlpanggilan berikut di aplikasi konsol C # saya:

curl -d "text=This is a block of text" \
    http://api.repustate.com/v2/demokey/score.json

Saya mencoba melakukan seperti pertanyaan yang diposting di sini , tetapi saya tidak dapat mengisi properti dengan benar.

Saya juga mencoba mengubahnya menjadi permintaan HTTP biasa:

http://api.repustate.com/v2/demokey/score.json?text="This%20is%20a%20block%20of%20text"

Bisakah saya mengonversi panggilan cURL menjadi permintaan HTTP? Jika ya, bagaimana caranya? Jika tidak, bagaimana saya dapat melakukan panggilan cURL di atas dari aplikasi konsol C # saya dengan benar?

smohamed
sumber
kemungkinan duplikat Mengunduh file menggunakan httprequest
Daniel Earwicker
@DanielEarwicker: Aku akan mengatakan tidak, hanya karena HttpClientadalah dalam campuran sekarang, dan itu akan menjadi yang cara untuk mendapatkan HTTP konten lebih HttpWebRequestdan WebClientmaju.
casperOne

Jawaban:

148

Nah, Anda tidak akan memanggil cURL secara langsung, Anda akan menggunakan salah satu opsi berikut:

Saya sangat merekomendasikan menggunakan HttpClientkelas, karena itu direkayasa untuk menjadi jauh lebih baik (dari sudut pandang kegunaan) daripada dua sebelumnya.

Dalam kasus Anda, Anda akan melakukan ini:

using System.Net.Http;

var client = new HttpClient();

// Create the HttpContent for the form to be posted.
var requestContent = new FormUrlEncodedContent(new [] {
    new KeyValuePair<string, string>("text", "This is a block of text"),
});

// Get the response.
HttpResponseMessage response = await client.PostAsync(
    "http://api.repustate.com/v2/demokey/score.json",
    requestContent);

// Get the response content.
HttpContent responseContent = response.Content;

// Get the stream of the content.
using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync()))
{
    // Write the output.
    Console.WriteLine(await reader.ReadToEndAsync());
}

Perhatikan juga bahwa HttpClientkelas memiliki dukungan yang jauh lebih baik untuk menangani jenis respons yang berbeda, dan dukungan yang lebih baik untuk operasi asinkron (dan pembatalannya) dari opsi yang disebutkan sebelumnya.

casperOne
sumber
7
Saya telah mencoba mengikuti kode Anda untuk masalah serupa tetapi saya diberi kesalahan yang menunggu hanya dapat disetel ke metode async?
Jay
@Jay Ya, asinkron dan menunggu adalah pasangan, Anda tidak dapat menggunakan satu tanpa yang lain. Ini berarti Anda harus membuat metode penampung (yang tidak ada di sini) async.
casperOne
1
@Jay Sebagian besar metode kembali Task<T>, Anda tidak dapat menggunakan asyncdan kemudian berurusan dengan jenis kembali secara normal (Anda harus menelepon Task<T>.Result. Catatan, Anda lebih baik menggunakan asyncmeskipun Anda membuang-buang thread menunggu hasilnya.
casperOne
1
@Maxsteel Ya, ini adalah susunan yang KeyValuePair<string, string>hanya akan Anda gunakannew [] { new KeyValuePair<string, string>("text", "this is a block of text"), new KeyValuePair<string, string>("activity[verb]", "testVerb") }
casperOne
1
Bisakah ini berfungsi untuk melakukan panggilan seperti ini? curl -k -i -H "Accept: application/json" -H "X-Application: <AppKey>" -X POST -d 'username=<username>&password=<password>' https://identitysso.betfair.com/api/login
Murray Hart
25

Atau di restSharp :

var client = new RestClient("https://example.com/?urlparam=true");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/x-www-form-urlencoded");
request.AddHeader("cache-control", "no-cache");
request.AddHeader("header1", "headerval");
request.AddParameter("application/x-www-form-urlencoded", "bodykey=bodyval", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Thomas secara online
sumber
1
Contoh penggunaan dasar tidak berhasil di luar kotak. restSharp adalah sampah.
Alex G
13

Di bawah ini adalah kode contoh yang berfungsi.

Harap dicatat Anda perlu menambahkan referensi ke Newtonsoft.Json.Linq

string url = "https://yourAPIurl";
WebRequest myReq = WebRequest.Create(url);
string credentials = "xxxxxxxxxxxxxxxxxxxxxxxx:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";
CredentialCache mycache = new CredentialCache();
myReq.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
WebResponse wr = myReq.GetResponse();
Stream receiveStream = wr.GetResponseStream();
StreamReader reader = new StreamReader(receiveStream, Encoding.UTF8);
string content = reader.ReadToEnd();
Console.WriteLine(content);
var json = "[" + content + "]"; // change this to array
var objects = JArray.Parse(json); // parse as array  
foreach (JObject o in objects.Children<JObject>())
{
    foreach (JProperty p in o.Properties())
    {
        string name = p.Name;
        string value = p.Value.ToString();
        Console.Write(name + ": " + value);
    }
}
Console.ReadLine();

Referensi: TheDeveloperBlog.com

BenW
sumber
3

Saya tahu ini adalah pertanyaan yang sangat lama tetapi saya memposting solusi ini jika itu membantu seseorang. Saya baru-baru ini menemui masalah ini dan google membawa saya ke sini. Jawabannya di sini membantu saya memahami masalahnya tetapi masih ada masalah karena kombinasi parameter saya. Apa yang akhirnya memecahkan masalah saya adalah konverter curl ke C # . Ini adalah alat yang sangat kuat dan mendukung sebagian besar parameter untuk Curl. Kode yang dihasilkannya dapat segera dijalankan.

Bob
sumber
3
Saya akan sangat berhati-hati untuk tidak menempelkan data sensitif apa pun (seperti cookie auth) di sana ...
Adi H
2

Respon terlambat tapi inilah yang akhirnya saya lakukan. Jika Anda ingin menjalankan perintah curl Anda sangat mirip seperti yang Anda jalankan di linux dan Anda memiliki windows 10 atau yang terakhir lakukan ini:

    public static string ExecuteCurl(string curlCommand, int timeoutInSeconds=60)
    {
        if (string.IsNullOrEmpty(curlCommand))
            return "";

        curlCommand = curlCommand.Trim();

        // remove the curl keworkd
        if (curlCommand.StartsWith("curl"))
        {
            curlCommand = curlCommand.Substring("curl".Length).Trim();
        }

        // this code only works on windows 10 or higher
        {

            curlCommand = curlCommand.Replace("--compressed", "");

            // windows 10 should contain this file
            var fullPath = System.IO.Path.Combine(Environment.SystemDirectory, "curl.exe");

            if (System.IO.File.Exists(fullPath) == false)
            {
                if (Debugger.IsAttached) { Debugger.Break(); }
                throw new Exception("Windows 10 or higher is required to run this application");
            }

            // on windows ' are not supported. For example: curl 'http://ublux.com' does not work and it needs to be replaced to curl "http://ublux.com"
            List<string> parameters = new List<string>();


            // separate parameters to escape quotes
            try
            {
                Queue<char> q = new Queue<char>();

                foreach (var c in curlCommand.ToCharArray())
                {
                    q.Enqueue(c);
                }

                StringBuilder currentParameter = new StringBuilder();

                void insertParameter()
                {
                    var temp = currentParameter.ToString().Trim();
                    if (string.IsNullOrEmpty(temp) == false)
                    {
                        parameters.Add(temp);
                    }

                    currentParameter.Clear();
                }

                while (true)
                {
                    if (q.Count == 0)
                    {
                        insertParameter();
                        break;
                    }

                    char x = q.Dequeue();

                    if (x == '\'')
                    {
                        insertParameter();

                        // add until we find last '
                        while (true)
                        {
                            x = q.Dequeue();

                            // if next 2 characetrs are \' 
                            if (x == '\\' && q.Count > 0 && q.Peek() == '\'')
                            {
                                currentParameter.Append('\'');
                                q.Dequeue();
                                continue;
                            }

                            if (x == '\'')
                            {
                                insertParameter();
                                break;
                            }

                            currentParameter.Append(x);
                        }
                    }
                    else if (x == '"')
                    {
                        insertParameter();

                        // add until we find last "
                        while (true)
                        {
                            x = q.Dequeue();

                            // if next 2 characetrs are \"
                            if (x == '\\' && q.Count > 0 && q.Peek() == '"')
                            {
                                currentParameter.Append('"');
                                q.Dequeue();
                                continue;
                            }

                            if (x == '"')
                            {
                                insertParameter();
                                break;
                            }

                            currentParameter.Append(x);
                        }
                    }
                    else
                    {
                        currentParameter.Append(x);
                    }
                }
            }
            catch
            {
                if (Debugger.IsAttached) { Debugger.Break(); }
                throw new Exception("Invalid curl command");
            }

            StringBuilder finalCommand = new StringBuilder();

            foreach (var p in parameters)
            {
                if (p.StartsWith("-"))
                {
                    finalCommand.Append(p);
                    finalCommand.Append(" ");
                    continue;
                }

                var temp = p;

                if (temp.Contains("\""))
                {
                    temp = temp.Replace("\"", "\\\"");
                }
                if (temp.Contains("'"))
                {
                    temp = temp.Replace("'", "\\'");
                }

                finalCommand.Append($"\"{temp}\"");
                finalCommand.Append(" ");
            }


            using (var proc = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "curl.exe",
                    Arguments = finalCommand.ToString(),
                    UseShellExecute = false,
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    CreateNoWindow = true,
                    WorkingDirectory = Environment.SystemDirectory
                }
            })
            {
                proc.Start();

                proc.WaitForExit(timeoutInSeconds*1000);

                return proc.StandardOutput.ReadToEnd();
            }
        }
    }

Alasan mengapa kodenya agak panjang adalah karena windows akan memberi Anda kesalahan jika Anda mengeksekusi satu kutipan. Dengan kata lain, perintah curl 'https://google.com'akan berfungsi di linux dan tidak akan berfungsi di windows. Berkat metode yang saya buat, Anda dapat menggunakan tanda kutip tunggal dan menjalankan perintah curl persis seperti yang Anda jalankan di linux. Kode ini juga memeriksa karakter yang keluar seperti \'dan \".

Misalnya gunakan kode ini sebagai

var output = ExecuteCurl(@"curl 'https://google.com' -H 'Accept: application/json, text/javascript, */*; q=0.01'");

Jika Anda menjalankan string yang sama di mana lagi C:\Windows\System32\curl.exeitu tidak akan berfungsi karena untuk beberapa alasan windows tidak menyukai tanda kutip tunggal.

Tono Nam
sumber
0

Panggil cURL dari aplikasi konsol Anda bukanlah ide yang bagus.

Tapi Anda bisa menggunakan TinyRestClient yang mempermudah pembuatan permintaan:

var client = new TinyRestClient(new HttpClient(),"https://api.repustate.com/");

client.PostRequest("v2/demokey/score.json").
AddQueryParameter("text", "").
ExecuteAsync<MyResponse>();
pengguna8803505
sumber
0

Nah jika Anda baru mengenal C # dengan cmd-line exp. Anda dapat menggunakan situs online seperti " https://curl.olsh.me/ " atau pencarian curl to C # converter akan mengembalikan situs yang dapat melakukannya untuk Anda.

atau jika Anda menggunakan tukang pos, Anda dapat menggunakan Hasilkan Cuplikan Kode hanya masalah dengan pembuat kode Postman adalah ketergantungan pada perpustakaan RestSharp.

Navid Golforoushan
sumber
0

Jangan lupa untuk menambahkan System.Net.Http, khususnya jika Anda menerima kesalahan ini:

Kode Keparahan Deskripsi Kesalahan Status Penekanan Baris File Proyek CS0246 Jenis atau nama namespace 'HttpClient' tidak dapat ditemukan (apakah Anda kehilangan petunjuk penggunaan atau referensi perakitan?) 1_default.aspx D: \ Projetos \ Testes \ FacebookAPI \ FB-CustomAudience \ default.aspx.cs 56 Aktif

Dalam hal ini Anda harus:

  1. Tambah System.Net.Http dari Nuget: Tools / NuGet Package Manager / Manager Paket NuGet untuk Solusi;
  2. Cari System.Net.Http
  3. Tambahkan di bagian atas halaman Anda kode berikut: using System.Net.Http;
Leandro Carvalho
sumber