简体   繁体   中英

curl POST into C#

I am trying to find a way how to transfer curl command to C#.

What i need is to obtain token from api and save it into file C:\\...\\x.json\\

Then i want to declare token into variable, and use it into another curl POST request to take data to work with them.

Curl:

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

My current try:

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

I tried several things, but none of them was working. This one is from curl.olsh.me but also i am getting some await error what i don't know what to do with it. (I am newbie in C#) :

The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.

curl -v output:

    • Trying 10.0.0.0...
    • TCP_NODELAY set
    • Connected to example.com (10.0.0.0) port 443 (#0)
    • ALPN, offering h2
    • ALPN, offering http/1.1
    • successfully set certificate verify locations:
    • CAfile: C:\\Users\\lvrabel\\Downloads\\curl-7.60.0-win64-mingw\\curl-7.60.0-win64-mingw\\bin\\curl-ca-bundle.crt CApath: none
    • TLSv1.2 (OUT), TLS handshake, Client hello (1):
    • TLSv1.2 (IN), TLS handshake, Server hello (2):
    • TLSv1.2 (IN), TLS handshake, Certificate (11):
    • TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    • TLSv1.2 (IN), TLS handshake, Server finished (14):
    • TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    • TLSv1.2 (OUT), TLS change cipher, Client hello (1):
    • TLSv1.2 (OUT), TLS handshake, Finished (20):
    • TLSv1.2 (IN), TLS handshake, Finished (20):
    • SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
    • ALPN, server did not agree to a protocol
    • Server certificate:
    • subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.example.com
    • start date: Dec 1 00:00:00 2016 GMT
    • expire date: Dec 1 23:59:59 2019 GMT
    • subjectAltName: host "example.com" matched cert's "*.example.com"
    • issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server
    • SSL certificate verify ok. < POST /cxf/IOTServices/v2/Login HTTP/1.1 < Host: example.com < User-Agent: curl/7.60.0 < accept: application/json < Content-Type: application/json < Content-Length: 64 <
    • upload completely sent off: 64 out of 64 bytes < HTTP/1.1 200 OK < Date: Mon, 24 Sep 2018 09:22:30 GMT < Content-Type: application/json < Date: Mon, 24 Sep 2018 09:22:31 GMT < Connection: close < Set-Cookie: TS0119a36f=015d568915873c94e852616fd92d5dd7a03a620f3cd2326781154684dfd7b31302f6fcb9822598d5a76466d0c6a25583fccbb30c7d; Path=/; Domain=.example.com < Transfer-Encoding: chunked < {"code":200,"status":"success","sessionId":"5cd92d80-bfdb-11e8-83c7-5b742f0c1244"}* Closing connection 0
    • TLSv1.2 (OUT), TLS alert, Client hello (1):

use this website 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);
    }
}

Async main methods is available in C# 7. If you're on an earlier version, you can handle the task 'manually' like this

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

You have to make the main method async :

static async void Main(string[] args)

If you are using C# version < 7.1, then you cannot use any await directly in Main . In this case you have to define a Task and .Wait() for it (instead of await for it).

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

I use the System.Net.Http.Formatting.Extension

example:

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

Update:

I got this response from server :

StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers: { Date: Tue, 25 Sep 2018 06:57:16 GMT Date: Tue, 25 Sep 2018 06:57:17 GMT Connection: close Set-Cookie: TS0119a36f=015d56898097bc7f5dccb374f352898f8806da5833c9f8a8ef4ff6ae2a2b1d4e78147fb79479f8bf85929406f34372c41c63572a89; Path=/; Domain=.example.com Transfer-Encoding: chunked Content-Type: application/json }

I think that there is some problem with encoding or idk. When i execute curl i get this output (the one i need):

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

Current code:

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

As far as I know you need to convert username and password to bytes, and take it as base 64 string and pass it to header. When you use await, if it is a void method then you should add async modifier with Task in its signature OR in case the method should return what ever type than use async Task as shown in the example. In that case you need to fetch the result, using result as shown in the test example. You can read more on this topic in Microsoft docs.

Here is the code:

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

Here is example of testing it:

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.
}

Links:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM