Thực hiện cuộc gọi cURL trong C #


89

Tôi muốn thực hiện curlcuộc gọi sau trong ứng dụng bảng điều khiển C # của mình:

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

Tôi đã cố gắng làm như câu hỏi được đăng ở đây , nhưng tôi không thể điền đúng các thuộc tính.

Tôi cũng đã cố gắng chuyển đổi nó thành một yêu cầu HTTP thông thường:

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

Tôi có thể chuyển đổi một cuộc gọi cURL thành một yêu cầu HTTP không? Nếu vậy, làm thế nào? Nếu không, làm cách nào để thực hiện lệnh gọi cURL ở trên từ ứng dụng bảng điều khiển C # của tôi đúng cách?



@DanielEarwicker: Tôi muốn nói nó không phải là, chỉ vì HttpClientlà trong hỗn hợp bây giờ, và nó sẽ là các cách để get HTTP nội dung trên HttpWebRequestWebClienttrong tương lai.
casperOne

Câu trả lời:


147

Chà, bạn sẽ không gọi cURL trực tiếp, thay vào đó, bạn sẽ sử dụng một trong các tùy chọn sau:

Tôi thực sự khuyên bạn nên sử dụng HttpClientlớp này, vì nó được thiết kế để tốt hơn nhiều (từ quan điểm khả năng sử dụng) so với hai lớp trước.

Trong trường hợp của bạn, bạn sẽ làm điều này:

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

Cũng lưu ý rằng HttpClientlớp này có hỗ trợ tốt hơn nhiều cho việc xử lý các kiểu phản hồi khác nhau và hỗ trợ tốt hơn cho các hoạt động không đồng bộ (và việc hủy bỏ chúng) so với các tùy chọn đã đề cập trước đó.


7
Tôi đã thử làm theo mã của bạn cho một vấn đề tương tự nhưng tôi nhận được lỗi mà chỉ có thể được đặt thành phương thức không đồng bộ?
Jay

@Jay Vâng, async và await là một cặp, bạn không thể sử dụng cái này mà không có cái kia. Điều này có nghĩa là bạn phải làm cho phương thức chứa (không có ở đây) không đồng bộ.
casperOne

1
@Jay Hầu hết các phương thức đó đều trả về Task<T>, bạn chỉ có thể không sử dụng asyncvà sau đó xử lý các loại trả về một cách bình thường (bạn phải gọi Task<T>.Result. Lưu ý, bạn nên sử dụng tốt hơn asyncmặc dù bạn đang lãng phí chuỗi chờ kết quả.
casperOne

1
@Maxsteel Vâng, đó là một mảng của KeyValuePair<string, string>do đó bạn sẽ chỉ cần sử dụngnew [] { new KeyValuePair<string, string>("text", "this is a block of text"), new KeyValuePair<string, string>("activity[verb]", "testVerb") }
casperOne

1
Điều này có thể hoạt động để thực hiện một cuộc gọi như thế này? 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

Hoặc trong 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
Ví dụ sử dụng cơ bản không hoạt động ngoài hộp. restSharp là rác.
Alex G

1
@AlexG Vậy thì bạn đang làm sai. Làm việc cho tôi.
dùng2924019

13

Dưới đây là một mã ví dụ hoạt động.

Xin lưu ý rằng bạn cần thêm tham chiếu đến 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();

Tham khảo: TheDeveloperBlog.com


3

Tôi biết đây là một câu hỏi rất cũ nhưng tôi đăng giải pháp này trong trường hợp nó giúp ích cho ai đó. Gần đây tôi đã gặp vấn đề này và google đã dẫn tôi đến đây. Câu trả lời ở đây giúp tôi hiểu vấn đề nhưng vẫn còn vấn đề do sự kết hợp tham số của tôi. Điều cuối cùng giải quyết được vấn đề của tôi là bộ chuyển đổi curl sang C # . Nó là một công cụ rất mạnh và hỗ trợ hầu hết các tham số cho Curl. Mã nó tạo ra gần như có thể chạy được ngay lập tức.


3
Tôi sẽ cẩn thận để không dán bất kỳ dữ liệu nhạy cảm nào (như cookie xác thực) vào đó ...
Adi H

2

Trả lời muộn nhưng đây là những gì tôi đã làm. Nếu bạn muốn chạy các lệnh curl của mình tương tự như khi bạn chạy chúng trên linux và bạn có Windows 10 trở lên, hãy thực hiện điều này:

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

Lý do tại sao mã hơi dài là vì cửa sổ sẽ cho bạn một lỗi nếu bạn thực hiện một dấu ngoặc kép. Nói cách khác, lệnh curl 'https://google.com'sẽ hoạt động trên linux và nó sẽ không hoạt động trên windows. Nhờ phương pháp đó mà tôi đã tạo, bạn có thể sử dụng các dấu nháy đơn và chạy các lệnh curl của mình chính xác như khi bạn chạy chúng trên linux. Mã này cũng kiểm tra các ký tự thoát như \'\".

Ví dụ: sử dụng mã này như

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

Nếu bạn chạy chuỗi tương tự C:\Windows\System32\curl.exeđó ở đâu thì nó sẽ không hoạt động vì vì lý do nào đó các cửa sổ không thích các dấu nháy đơn.


0

Gọi cURL từ ứng dụng bảng điều khiển của bạn không phải là một ý tưởng hay.

Nhưng bạn có thể sử dụng TinyRestClient để tạo yêu cầu dễ dàng hơn:

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

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

0

Vâng nếu bạn là người mới sử dụng C # với cmd-line exp. bạn có thể sử dụng các trang web trực tuyến như " https://curl.olsh.me/ " hoặc trình chuyển đổi tìm kiếm curl sang C # sẽ trả về trang web có thể làm điều đó cho bạn.

hoặc nếu bạn đang sử dụng người đưa thư, bạn có thể sử dụng Tạo mã đoạn mã chỉ có vấn đề với trình tạo mã Postman là sự phụ thuộc vào thư viện RestSharp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.