【问题标题】:curl POST into C#将 POST 卷曲到 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 检查我的答案,这可能会解决您的问题。

标签: c# curl


【解决方案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.
}

链接:

【讨论】:

  • 可以显示请求代码吗?这是有问题的帖子数据的传递。我也一直在使用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;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-08-12
          • 2015-01-06
          • 2018-09-20
          • 2011-05-15
          • 1970-01-01
          • 2019-11-02
          • 2019-03-31
          相关资源
          最近更新 更多