Einen CURL-Aufruf in C #

87

Ich möchte curlin meiner C # -Konsolenanwendung den folgenden Aufruf tätigen :

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

Ich habe versucht, die hier gepostete Frage zu mögen , aber ich kann die Eigenschaften nicht richtig ausfüllen.

Ich habe auch versucht, es in eine reguläre HTTP-Anfrage zu konvertieren:

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

Kann ich einen cURL-Aufruf in eine HTTP-Anforderung konvertieren? Wenn das so ist, wie? Wenn nicht, wie kann ich den obigen cURL-Aufruf von meiner C # -Konsolenanwendung aus ordnungsgemäß ausführen?

smohamed
quelle
Mögliches Duplikat des Herunterladens von Dateien mit httprequest
Daniel Earwicker
@ DanielEarwicker: Ich würde sagen, dass dies nicht der Fall ist, nur weil HttpClientes jetzt in der Mischung ist und es der Weg sein wird, HTTP-Inhalte zu überarbeiten HttpWebRequestund WebClientvoranzukommen.
CasperOne

Antworten:

144

Nun, Sie würden cURL nicht direkt aufrufen , sondern eine der folgenden Optionen verwenden:

Ich würde die Verwendung der HttpClientKlasse wärmstens empfehlen , da sie (unter dem Gesichtspunkt der Benutzerfreundlichkeit) viel besser ist als die beiden vorherigen.

In Ihrem Fall würden Sie Folgendes tun:

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

Beachten Sie auch, dass die HttpClientKlasse eine viel bessere Unterstützung für die Behandlung verschiedener Antworttypen und eine bessere Unterstützung für asynchrone Operationen (und deren Abbruch) gegenüber den zuvor genannten Optionen bietet.

casperOne
quelle
7
Ich habe versucht, Ihrem Code für ein ähnliches Problem zu folgen, aber mir werden Fehler angezeigt, die nur auf asynchrone Methoden gesetzt werden können.
Jay
@ Jay Ja, Async und Warten sind ein Paar, Sie können eins nicht ohne das andere verwenden. Dies bedeutet, dass Sie die enthaltende Methode (von der es hier keine gibt) asynchron machen müssen.
CasperOne
1
@Jay Die meisten dieser Methoden geben zurück Task<T>, Sie können asyncdie Rückgabetypen einfach nicht verwenden und dann normal behandeln (Sie müssten sie aufrufen Task<T>.Result. Beachten Sie jedoch, dass Sie sie besser verwenden sollten, asyncda Sie den Thread verschwenden, der auf das Ergebnis wartet.
CasperOne
1
@ Maxsteel Ja, es ist ein Array von KeyValuePair<string, string>so würden Sie nur verwendennew [] { new KeyValuePair<string, string>("text", "this is a block of text"), new KeyValuePair<string, string>("activity[verb]", "testVerb") }
casperOne
1
Kann dies funktionieren, um einen solchen Anruf zu tätigen? 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
22

Oder in 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);
online Thomas
quelle
1
Das grundlegende Verwendungsbeispiel funktioniert nicht sofort. restSharp ist Müll.
Alex G
@AlexG Dann machst du es falsch. Funktioniert bei mir.
user2924019
13

Unten finden Sie einen funktionierenden Beispielcode.

Bitte beachten Sie, dass Sie einen Verweis auf Newtonsoft.Json.Linq hinzufügen müssen

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

Referenz: TheDeveloperBlog.com

BenW
quelle
2

Späte Antwort, aber genau das habe ich getan. Wenn Sie Ihre Curl-Befehle sehr ähnlich ausführen möchten, wie Sie sie unter Linux ausführen und Windows 10 oder höher verwenden, gehen Sie folgendermaßen vor:

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

Der Grund, warum der Code etwas lang ist, liegt darin, dass Windows Ihnen einen Fehler gibt, wenn Sie ein einfaches Anführungszeichen ausführen. Mit anderen Worten, der Befehl curl 'https://google.com'funktioniert unter Linux und nicht unter Windows. Dank dieser von mir erstellten Methode können Sie einfache Anführungszeichen verwenden und Ihre Curl-Befehle genau so ausführen, wie Sie sie unter Linux ausführen. Dieser Code prüft auch, ob Zeichen wie \'und maskiert werden \".

Verwenden Sie diesen Code beispielsweise als

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

Wenn Sie dieselbe Zeichenfolge erneut ausführen möchten C:\Windows\System32\curl.exe, funktioniert dies nicht, da Windows aus irgendeinem Grund keine einfachen Anführungszeichen mag.

Tono Nam
quelle
2

Ich weiß, dass dies eine sehr alte Frage ist, aber ich poste diese Lösung für den Fall, dass sie jemandem hilft. Ich bin kürzlich auf dieses Problem gestoßen und Google hat mich hierher geführt. Die Antwort hier hilft mir, das Problem zu verstehen, aber es gibt immer noch Probleme aufgrund meiner Parameterkombination. Was mein Problem schließlich löst, ist Curl to C # -Konverter . Es ist ein sehr leistungsfähiges Werkzeug und unterstützt die meisten Parameter für Curl. Der generierte Code kann fast sofort ausgeführt werden.

Bob
quelle
2
Ich würde sehr vorsichtig sein, keine sensiblen Daten (wie Auth-Cookies) dort einzufügen ...
Adi H
0

Das Aufrufen von cURL über Ihre Konsolen-App ist keine gute Idee.

Sie können jedoch TinyRestClient verwenden , um das Erstellen von Anforderungen zu vereinfachen:

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

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

Nun, wenn Sie neu in C # mit cmd-line exp sind. Sie können Online-Sites wie " https://curl.olsh.me/ " verwenden oder "Curl to C # Converter" suchen, um eine Site zurückzugeben, die dies für Sie tun könnte.

oder wenn Sie Postman verwenden, können Sie Code-Snippet generieren verwenden. Das einzige Problem mit dem Postman-Code-Generator ist die Abhängigkeit von der RestSharp-Bibliothek.

Navid Golforoushan
quelle