7
votes

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):
6
Your method sig should look like: static async void Main(string[] args). You add the async keyword.Stuart
Hi @Stuart, then i don't understand it, because when i change Main method then i got error : Program does not contain static Main method suitable for an entry pointLukasV
You might want to define a task method, and then call that from within Main...Stuart
@LukášVrábel check my answer, that might solve your issue.maytham-ɯɐɥʇʎɐɯ

6 Answers

4
votes

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

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;
2
votes

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);
1
votes

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

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

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: