Здійснення виклику curl на C #


89

Я хочу зробити наступний curlвиклик у моїй консольній програмі C #:

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

Я намагався зробити, як запитання, розміщене тут , але я не можу правильно заповнити властивості.

Я також спробував перетворити його на звичайний HTTP-запит:

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

Чи можу я перетворити виклик curl на запит HTTP? Якщо так, то як? Якщо ні, як я можу зробити вищевказаний виклик cURL із моєї консольної програми C # належним чином?



@DanielEarwicker: Я б сказав , що це не тільки тому , що HttpClientзнаходиться в з'єднанні зараз, і це буде спосіб отримати HTTP контенту через та йти вперед. HttpWebRequestWebClient
casperOne

Відповіді:


147

Ну, ви б не викликали cURL безпосередньо, скоріше, скористалися б одним із таких варіантів:

Я настійно рекомендую використовувати HttpClientклас, оскільки він спроектований набагато краще (з точки зору юзабіліті), ніж попередні два.

У вашому випадку ви зробите це:

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

Також зауважте, що HttpClientклас має набагато кращу підтримку для обробки різних типів відповідей та кращу підтримку асинхронних операцій (та їх скасування) порівняно з раніше згаданими опціями.


7
Я намагався слідувати за вашим кодом для подібної проблеми, але мені видають помилки, які очікують, можна встановити лише як асинхронні методи?
Джей

@Jay Так, async і await - пара, ви не можете використовувати одне без іншого. Це означає, що ви повинні зробити вміщуючий метод (якого тут немає) асинхронним.
casperOne

1
@Jay Більшість із цих методів повертаються Task<T>, ви можете просто не використовувати, asyncа потім мати справу із типами повернення, як правило (вам доведеться зателефонувати Task<T>.Result. Зверніть увагу, ви краще використовуєте, asyncхоча витрачаєте нитку на очікування результату.
casperOne

1
@Maxsteel Так, це масив, KeyValuePair<string, string>тому ви б просто використовувалиnew [] { new KeyValuePair<string, string>("text", "this is a block of text"), new KeyValuePair<string, string>("activity[verb]", "testVerb") }
casperOne

1
Чи може це спрацювати для здійснення такого дзвінка? curl -k -i -H "Accept: application/json" -H "X-Application: <AppKey>" -X POST -d 'username=<username>&password=<password>' https://identitysso.betfair.com/api/login
Мюррей Харт

25

Або в 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);

1
Основний приклад використання не працює нестандартно. restSharp - це мотлох.
Alex G

1
@AlexG Тоді ти робиш це неправильно. Працює для мене.
user2924019

13

Нижче наведено робочий приклад коду.

Зверніть увагу, що вам потрібно додати посилання на 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();

Довідково: TheDeveloperBlog.com


3

Я знаю, що це дуже давнє запитання, але я публікую це рішення, якщо воно комусь допоможе. Нещодавно я зіткнувся з цією проблемою, і Google привів мене сюди. Відповідь тут допомагає мені зрозуміти проблему, але все ще є проблеми через мою комбінацію параметрів. Що врешті-решт вирішує мою проблему, це конвертер в C # . Це дуже потужний інструмент, який підтримує більшість параметрів Curl. Код, який він генерує, майже відразу можна запустити.


3
Я був би обережним, щоб не вставити туди ніяких конфіденційних даних (наприклад, файли cookie для автентифікації) ...
Аді Х,

2

Пізня відповідь, але це те, що я закінчив робити. Якщо ви хочете запускати свої команди curl дуже подібно до того, як ви запускаєте їх на Linux, і у вас є Windows 10 або пізніша версія, зробіть це:

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

Причина, через яку код трохи довгий, полягає в тому, що Windows видасть вам помилку, якщо ви виконаєте одну цитату. Іншими словами, команда curl 'https://google.com'буде працювати в Linux, а в Windows - не. Завдяки тому методу, який я створив, ви можете використовувати одинарні лапки та запускати свої команди curl точно так, як ви запускаєте їх на Linux. Цей код також перевіряє наявність символів екранування, таких як \'і \".

Наприклад, використовуйте цей код як

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

Якщо вам потрібно де запустити той самий рядок знову, C:\Windows\System32\curl.exeце не буде працювати, тому що Windows чомусь не любить одинарні лапки.


0

Зателефонувати cURL із консольного додатка - це не дуже гарна ідея.

Але ви можете використовувати TinyRestClient, що полегшує створення запитів:

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

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

0

Добре, якщо ви новачок у C # з cmd-line exp. Ви можете використовувати веб-сайти, такі як " https://curl.olsh.me/ ", або пошук curl для перетворювача C # поверне сайт, який міг би зробити це за вас.

або якщо ви використовуєте листоношу, ви можете використовувати "Створити фрагмент коду". Проблема лише з генератором коду Поштовик - це залежність від бібліотеки RestSharp.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.