Faire un appel cURL en C #

89

Je souhaite effectuer l' curlappel suivant dans mon application console C #:

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

J'ai essayé de faire comme la question posée ici , mais je ne peux pas remplir correctement les propriétés.

J'ai également essayé de le convertir en une requête HTTP régulière:

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

Puis-je convertir un appel cURL en une requête HTTP? Si c'est le cas, comment? Sinon, comment puis-je effectuer correctement l'appel cURL ci-dessus à partir de mon application console C #?

smohamed
la source
duplication possible du téléchargement de fichiers via httprequest
Daniel Earwicker
@DanielEarwicker: Je dirais que ce n'est pas le cas, uniquement parce que HttpClientc'est dans le mix maintenant, et ça va être le moyen de faire passer le contenu HTTP HttpWebRequestet d' WebClientaller de l'avant.
casperOne

Réponses:

147

Eh bien, vous n'appelez pas directement cURL , vous utilisez plutôt l'une des options suivantes:

Je recommande vivement d'utiliser la HttpClientclasse, car elle est conçue pour être bien meilleure (du point de vue de la convivialité) que les deux précédentes.

Dans votre cas, vous feriez ceci:

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

Notez également que la HttpClientclasse a un bien meilleur support pour la gestion de différents types de réponse, et un meilleur support pour les opérations asynchrones (et leur annulation) par rapport aux options mentionnées précédemment.

casperOne
la source
7
J'ai essayé de suivre votre code pour un problème similaire, mais on me donne des erreurs qui attendent ne peuvent être définies que sur des méthodes asynchrones?
Jay le
@Jay Oui, async et await sont une paire, vous ne pouvez pas utiliser l'un sans l'autre. Cela signifie que vous devez rendre la méthode contenant (dont il n'y en a pas ici) asynchrone.
casperOne
1
@Jay La plupart de ces méthodes retournent Task<T>, vous ne pouvez tout simplement pas utiliser asyncpuis traiter les types de retour normalement (vous devrez appeler Task<T>.Result. Notez que vous feriez mieux d'utiliser asyncsi vous gaspillez le thread en attendant le résultat.
casperOne
1
@Maxsteel Oui, c'est un tableau de KeyValuePair<string, string>donc vous utiliseriez simplementnew [] { new KeyValuePair<string, string>("text", "this is a block of text"), new KeyValuePair<string, string>("activity[verb]", "testVerb") }
casperOne
1
Cela peut-il fonctionner pour passer un appel comme celui-ci? 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
24

Ou dans 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);
en ligne Thomas
la source
1
L'exemple d'utilisation de base ne fonctionne pas immédiatement. restSharp est indésirable.
Alex G
1
@AlexG Vous vous trompez alors. Travaille pour moi.
user2924019
13

Voici un exemple de code fonctionnel.

Veuillez noter que vous devez ajouter une référence à 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();

Référence: TheDeveloperBlog.com

BenW
la source
3

Je sais que c'est une question très ancienne mais je publie cette solution au cas où cela aiderait quelqu'un. J'ai récemment rencontré ce problème et Google m'a conduit ici. La réponse ici m'aide à comprendre le problème, mais il y a toujours des problèmes dus à ma combinaison de paramètres. Ce qui résout finalement mon problème, c'est le convertisseur curl en C # . C'est un outil très puissant et prend en charge la plupart des paramètres de Curl. Le code qu'il génère est exécutable presque immédiatement.

Bob
la source
3
Je ferais très attention de ne pas coller de données sensibles (comme les cookies d'authentification) là-dessus ...
Adi H
2

Réponse tardive mais c'est ce que j'ai fini par faire. Si vous souhaitez exécuter vos commandes curl de la même manière que vous les exécutez sous Linux et que vous avez Windows 10 ou une version ultérieure, procédez comme suit:

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

La raison pour laquelle le code est un peu long est que Windows vous donnera une erreur si vous exécutez un guillemet simple. En d'autres termes, la commande curl 'https://google.com'fonctionnera sous Linux et ne fonctionnera pas sous Windows. Grâce à cette méthode que j'ai créée, vous pouvez utiliser des guillemets simples et exécuter vos commandes curl exactement comme vous les exécutez sous Linux. Ce code vérifie également les caractères d'échappement tels que \'et \".

Par exemple, utilisez ce code comme

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

Si vous exécutez à nouveau la même chaîne, C:\Windows\System32\curl.execela ne fonctionnera pas car pour une raison quelconque, Windows n'aime pas les guillemets simples.

Tono Nam
la source
0

Appeler cURL depuis votre application console n'est pas une bonne idée.

Mais vous pouvez utiliser TinyRestClient qui facilite la création de requêtes:

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

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

Eh bien, si vous êtes nouveau en C # avec cmd-line exp. vous pouvez utiliser des sites en ligne comme " https://curl.olsh.me/ " ou rechercher un convertisseur curl en C # retournera un site qui pourrait le faire pour vous.

ou si vous utilisez Postman, vous pouvez utiliser Generate Code Snippet. Seul problème avec le générateur de code Postman est la dépendance à la bibliothèque RestSharp.

Navid Golforoushan
la source