C # 'da cURL çağrısı yapma


89

curlC # konsol uygulamamda aşağıdaki çağrıyı yapmak istiyorum :

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

Ben yayınlanmıştır soru gibi yapmaya çalıştım burada , ama düzgün dolgu özellikleriyle olamaz.

Ayrıca bunu normal bir HTTP isteğine dönüştürmeyi denedim:

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

Bir cURL çağrısını HTTP isteğine dönüştürebilir miyim? Öyleyse nasıl? Değilse, yukarıdaki cURL çağrısını C # konsol uygulamamdan nasıl düzgün bir şekilde yapabilirim?



@DanielEarwicker: Bunun olmadığını söyleyebilirim, sadece HttpClientşu anda karışımda olduğu içinHttpWebRequest ve HTTP içeriğini tekrar ve WebClientileriye götürmenin yolu bu olacak.
casperOne

Yanıtlar:


148

Doğrudan cURL'yi çağırmazsınız , bunun yerine aşağıdaki seçeneklerden birini kullanırsınız:

HttpClientEski ikisinden (kullanılabilirlik açısından) çok daha iyi olacak şekilde tasarlandığı için sınıfı kullanmanızı şiddetle tavsiye ederim .

Senin durumunda şunu yaparsın:

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

Ayrıca, HttpClientsınıfın farklı yanıt türlerini işlemek için çok daha iyi desteğe sahip olduğunu ve daha önce belirtilen seçeneklere göre zaman uyumsuz işlemler (ve bunların iptali) için daha iyi destek sağladığını unutmayın .


7
Kodunuzu benzer bir sorun için izlemeyi denedim, ancak bekleyen hatalar sadece zaman uyumsuz yöntemlere ayarlanabiliyor mu?
Jay

@Jay Evet, async ve await bir çift, birini diğeri olmadan kullanamazsınız. Bu, içeren yöntemi (burada hiçbiri olmayan) eşzamansız yapmanız gerektiği anlamına gelir.
casperOne

1
@Jay Bu yöntemlerin çoğu geri döner Task<T>, sadece kullanamazsınız asyncve sonra dönüş türlerini normal olarak halledemezsiniz (aramanız gerekir Task<T>.Result. Not, asyncsonucu bekleyen iş parçacığını boşa harcarken kullanmak daha iyidir .
casperOne

1
@Maxsteel Evet, KeyValuePair<string, string>sadece kullanmanız gereken bir dizinew [] { new KeyValuePair<string, string>("text", "this is a block of text"), new KeyValuePair<string, string>("activity[verb]", "testVerb") }
casperOne

1
Bu, böyle bir arama yapmak için işe yarayabilir mi? 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

Veya dinlenme halindeSharp :

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

1
Temel kullanım örneği kutudan çıkar çıkmaz işe yaramaz. restSharp önemsizdir.
Alex G

13

Aşağıda çalışan bir örnek kod bulunmaktadır.

Newtonsoft.Json.Linq'e bir referans eklemeniz gerektiğini lütfen unutmayın

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

Referans: TheDeveloperBlog.com


3

Bunun çok eski bir soru olduğunu biliyorum ama birine yardımcı olması durumunda bu çözümü gönderiyorum. Geçenlerde bu problemle karşılaştım ve google beni buraya yönlendirdi. Buradaki cevap, sorunu anlamama yardımcı oluyor, ancak parametre kombinasyonumdan dolayı hala sorunlar var. Sonunda sorunumu çözen şey curl'den C #'ye dönüştürücü . Çok güçlü bir araçtır ve Curl için çoğu parametreyi destekler. Oluşturduğu kod neredeyse anında çalıştırılabilir.


3
Oraya hassas veriler (kimlik doğrulama çerezleri gibi) yapıştırmamaya dikkat ederim ...
Adi H

2

Geç yanıt ama sonunda bunu yaptım. Curl komutlarınızı linux üzerinde çalıştırdığınızla çok benzer şekilde çalıştırmak istiyorsanız ve Windows 10 veya sonraki sürümlere sahipseniz bunu yapın:

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

Kodun biraz uzun olmasının nedeni, tek bir alıntı yaparsanız pencerelerin size bir hata vermesidir. Diğer bir deyişle, komut curl 'https://google.com'linux üzerinde çalışacak ve windows üzerinde çalışmayacaktır. Oluşturduğum bu yöntem sayesinde, tek tırnak işaretlerini kullanabilir ve curl komutlarınızı tam olarak linux üzerinde çalıştırdığınız gibi çalıştırabilirsiniz. Bu kod ayrıca \'ve gibi karakterlerin çıkışını da denetler \".

Örneğin bu kodu şu şekilde kullanın:

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

Aynı dizeyi tekrar nerede çalıştırırsanız C:\Windows\System32\curl.exeçalışmayacaktır çünkü bazı nedenlerden dolayı pencereler tek tırnak işaretlerini sevmez.


0

Konsol uygulamanızdan cURL çağrısı yapmak iyi bir fikir değildir.

Ancak, istek oluşturmayı kolaylaştıran TinyRestClient'i kullanabilirsiniz :

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

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

0

Peki, cmd-line exp ile C # konusunda yeniyseniz. " https://curl.olsh.me/ " gibi çevrimiçi siteleri kullanabilirsiniz veya curl to C # çevirici, bunu sizin için yapabilecek siteyi döndürür.

veya postacı kullanıyorsanız, Kod Parçacığı Oluştur'u kullanabilirsiniz. Postacı kod üretecindeki tek sorun, RestSharp kitaplığına bağımlılıktır.


0

System.Net.Http eklemeyi unutmayın, özellikle bu hatayı alırsanız:

Önem Kodu Açıklama Proje Dosyası Satır Gizleme Durum Hatası CS0246 'HttpClient' türü veya ad alanı adı bulunamadı (kullanma yönergesi veya bir derleme başvurusu eksik mi?) 1_default.aspx D: \ Projetos \ Testes \ FacebookAPI \ FB-CustomAudience \ default.aspx.cs 56 Etkin

Bu durumda şunu yapmanız gerekir:

  1. Nuget'ten System.Net.Http ekleyin: Tools / NuGet Package Manager / Manager NuGet Packages for Solution;
  2. System.Net.Http'yi arayın
  3. Sayfanızın en üstüne şu kodu ekleyin: using System.Net.Http;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.