将 POST 卷曲到 C#

Posted

技术标签:

【中文标题】将 POST 卷曲到 C#【英文标题】:curl POST into C# 【发布时间】:2019-02-25 19:58:27 【问题描述】:

我正在尝试找到一种将 curl 命令传输到 C# 的方法。

我需要的是从 api 获取令牌并将其保存到文件 C:\...\x.json\

然后我想将令牌声明为变量,并将其用于另一个 curl POST 请求以获取数据以使用它们。

卷曲:

curl -X POST "https://example.com" 
-H "accept: application/json" 
-H "Content-Type: application/json" 
-d "username":"username","password":"password"

我目前的尝试:

static void Main(string[] args)

    using (var httpClient = new HttpClient())
    
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://example.com"))
        
            request.Headers.TryAddWithoutValidation("Accept", "application/json");

            request.Content = new StringContent("\"username\":\"username\",\"password\":\"password\"", Encoding.UTF8, "application/json");

            var response = await httpClient.SendAsync(request);
        
                            

我尝试了几件事,但都没有奏效。这个来自 curl.olsh.me 但我也收到了一些等待错误,我不知道如何处理它。 (我是 C# 的新手):

“await”运算符只能在异步方法中使用。考虑使用 'async' 修饰符标记此方法并将其返回类型更改为 'Task'。

curl -v 输出:

正在尝试 10.0.0.0... TCP_NODELAY 设置 已连接到 example.com (10.0.0.0) 端口 443 (#0) ALPN,提供 h2 ALPN,提供 http/1.1 成功设置证书验证位置: CAfile: C:\Users\lvrabel\Downloads\curl-7.60.0-win64-mingw\curl-7.60.0-win64-mingw\bin\curl-ca-bundle.crt CApath:无 TLSv1.2 (OUT)、TLS 握手、客户端问候 (1): TLSv1.2 (IN)、TLS 握手、服务器问候 (2): TLSv1.2 (IN)、TLS 握手、证书 (11): TLSv1.2 (IN)、TLS 握手、服务器密钥交换 (12): TLSv1.2 (IN),TLS 握手,服务器完成 (14): TLSv1.2 (OUT)、TLS 握手、客户端密钥交换 (16): TLSv1.2 (OUT),TLS 更改密码,客户端问候 (1): TLSv1.2 (OUT),TLS 握手,完成 (20): TLSv1.2 (IN),TLS 握手,完成 (20): 使用 TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 的 SSL 连接 ALPN,服务器不同意协议 服务器证书: 主题:OU=域控制已验证; OU=PositiveSSL 通配符; CN=*.example.com 开始日期:格林威治标准时间 2016 年 12 月 1 日 00:00:00 到期日期:格林威治标准时间 2019 年 12 月 1 日 23:59:59 subjectAltName:主机“example.com”匹配证书的“*.example.com” 发行人:C=GB; ST=大曼彻斯特; L=索尔福德; O=COMODO CA 有限公司; CN=COMODO RSA 域验证安全服务器 SSL 证书验证正常。 上传完全发送:64 个字节中的 64 个 TLSv1.2 (OUT)、TLS 警报、客户端问候 (1):

【问题讨论】:

您的方法签名应如下所示:static async void Main(string[] args)。您添加 async 关键字。 嗨@Stuart,那我不明白,因为当我更改 Main 方法时出现错误:程序不包含适合入口点的静态 Main 方法 您可能想要定义一个任务方法,然后从 Main... 中调用它... @LukášVrábel 检查我的答案,这可能会解决您的问题。 【参考方案1】:

据我所知,您需要将用户名和密码转换为字节,并将其作为 base 64 字符串并将其传递给标题。当您使用 await 时,如果它是一个 void 方法,那么您应该在其签名中添加带有 Task 的 async 修饰符,或者如果该方法应该返回任何类型而不是使用 async Task ,如示例中所示。在这种情况下,您需要使用测试示例中所示的结果来获取结果。您可以在Microsoft docs 中阅读有关此主题的更多信息。

代码如下:

public async Task<HttpResponseMessage> CreateAuthorization(string url, string username, string password)

    HttpResponseMessage response;

    using (var httpClient = new HttpClient())
    
        using (var request = new HttpRequestMessage(new HttpMethod("POST"), url))
        
            request.Headers.TryAddWithoutValidation("Accept", "application/json");
            var authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes($"username:password"));
            request.Headers.TryAddWithoutValidation("Authorization", $"Basic authorization");
            response = await httpClient.SendAsync(request);
        
    

    return response;

这是测试它的示例:

public void CreateAuthorizationTest()

    var response = CreateAuthorization("https://example.com", "username", "password");
    var result = response.Result;
    var o = result.Content.ReadAsStringAsync();

    if (result.IsSuccessStatusCode)
    
        //do some thing if success
        // you can do deserialization what ever
        Console.WriteLine(o);
    
    else
    
        //do some thing if error
        Console.WriteLine(o);
    
    //etc.

链接:

How and when to use ‘async’ and ‘await’ https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

【讨论】:

可以显示请求代码吗?这是有问题的帖子数据的传递。我也一直在使用application/x-www-form-urlencoded @user1274820 只是为了确保另一个答案得到了赏金,所以我假设你得到了答案。所以我也假设我的回答是无关紧要的。如果您认为我可以贡献更多,请告诉我,以便我有空时可以查看它,现在是深夜在我的位置。 Wtf 我给了你赏金......你应该得到它,伙计 我开始了另一个赏金 - 我可以在 23 小时内奖励给你? 对不起那个人 没问题我很高兴你解决了它。祝你好运【参考方案2】:

使用本网站 https://curl.olsh.me/

using (var httpClient = new HttpClient())

    using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://example.com/"))
    
        request.Headers.TryAddWithoutValidation("Accept", "application/json"); 

        request.Content = new StringContent("\"username\":\"username\",\"password\":\"password\"", Encoding.UTF8, "application/json"); 

        var response = await httpClient.SendAsync(request);
    

【讨论】:

【参考方案3】:

更新:

我收到了服务器的回复:

StatusCode:200,ReasonPhrase:'OK',版本:1.1,内容:System.Net.Http.StreamContent,标题: 日期:2018 年 9 月 25 日星期二 06:57:16 GMT 日期:2018 年 9 月 25 日星期二 06:57:17 GMT 连接:关闭 设置 Cookie:TS0119a36f=015d56898097bc7f5dccb374f352898f8806da5833c9f8a8ef4ff6ae2a2b1d4e78147fb79479f8bf85929406f34372c41c63572a89;路径=/;域=.example.com 传输编码:分块 内容类型:应用程序/json

我认为编码或 idk 存在一些问题。当我执行 curl 我得到这个输出(我需要的那个):

"code":200,"status":"success","sessionId":"350bf800-bfdb-11e8-991a-d35510009464"

当前代码:

    static void Main(string[] args)
    
        using (var httpClient = new HttpClient())
        
            using (var request = new HttpRequestMessage(new HttpMethod("POST"), "https://api.example.com"))
            
                request.Headers.TryAddWithoutValidation("accept", "application/json");
                request.Content = new StringContent("\"username\":\"user\",\"password\":\"pass\"", Encoding.UTF8, "application/json");

                var task = httpClient.SendAsync(request);
                task.Wait();
                var response = task.Result;

                Console.WriteLine(response);
                Console.ReadKey();
            
        
    

【讨论】:

【参考方案4】:

C# 7 中提供了异步主要方法。如果您使用的是早期版本,则可以像这样“手动”处理任务

var task = httpClient.SendAsync(request);
task.Wait();
var response = task.Result;
Console.WriteLine(response.Content.ReadAsStringAsync().Result);

【讨论】:

很不错,谢谢。我现在确实有来自服务器的响应,但遗憾的是我只看到了这个:StatusCode:200,ReasonPhrase:'OK',版本:1.1,内容:System.Net.Http.StreamContent,标题:哪里也应该是令牌,但我没看到。 实际上更具体地说,从 7.1 开始 @LukášVrábel 由于您收到 200 返回码,因此调用将通过服务器。如果您可以访问它以查看发生了什么,您可以尝试在服务器端进行调试。如果您无权访问服务器,您可以尝试让电话与 Postman 或类似的东西一起工作。 遗憾的是我无法访问该服务器。令牌的语法类似于:6fa3ea90-bc02-11e8-991a-d35512019464。这应该是编码的问题吧? 你能在你的问题中发布 curl 的输出吗?【参考方案5】:

我使用 System.Net.Http.Formatting.Extension

示例:

using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
// Add NuGet package System.Net.Http.Formatting.Extension
namespace SimpleRestCall

    class Program
    
        static CancellationTokenSource cts = new CancellationTokenSource();

        static readonly string sitePath = "https://example.com";
        static void Main(string[] args)
        
            using (var client = new HttpClient  BaseAddress = new Uri(sitePath), Timeout = new TimeSpan(0, 1, 0) )
            
                Task.Run(() => Login(client)).Wait();
            
        

        private static async Task Login(HttpClient client)
        
            string path = ""; // if it's a controller path put it here
            LoginData postData = new LoginData  username = "username", password = "password" ;
            string json;
            using (HttpResponseMessage resp = await client.PostAsJsonAsync(path, postData, cts.Token))
            
                json = await resp.Content.ReadAsStringAsync();
            
            Console.WriteLine(json);
            Console.WriteLine("Press a key to finish");
            string aa = Console.ReadLine();
        

        private class LoginData
        
            public string username  get; set; 
            public string password  get; set; 
        
    

【讨论】:

【参考方案6】:

你要让main方法async:

static async void Main(string[] args)

如果您使用的是 C# 版本 Main 中使用任何 await。在这种情况下,您必须为它定义一个Task.Wait()(而不是为它定义await)。

Task task = ....;
task.Wait();
var result = task.Result;

【讨论】:

以上是关于将 POST 卷曲到 C#的主要内容,如果未能解决你的问题,请参考以下文章

PHP 卷曲,POST JSON

php 卷曲请求类(GET,POST)

php 卷曲请求类(GET,POST)

sh 卷曲POST

javascript WP - 使用Ajax进行卷曲POST

处理大卷曲响应 - PHP