Share via


convert curl command to c#

Question

Thursday, June 29, 2017 6:17 PM | 1 vote

Hi

can someone please help me convert curl command to c# .net4.0.
I am getting WebException:"The remote server returned an error: (400) Bad Request" with code below

command:
curl -X POST \
    -d 'grant_type=password' \
    -d 'client_id=client_id_value' \
    -d 'client_secret=client_secret_value' \
    -d 'username=name' \
    -d 'password=pwd' \
    'https://someurl'
   
Notes:      Request header must be set to x-www-form-urlencoded

code:
string url = "https://someurl";
WebRequest request = WebRequest.Create(url);

request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";

string authInfo = "name:pwd";
request.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(authInfo));

byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes("grant_type=password&client_id=client_id_value&client_secret=client_secret_value");
Stream reqstr = request.GetRequestStream();
reqstr.Write(buffer, 0, buffer.Length);
reqstr.Close();

WebResponse response = request.GetResponse();

Thanks!

All replies (8)

Tuesday, July 4, 2017 5:24 PM âś…Answered | 1 vote

Turns out I had troubles connecting because they required TLS version 1.2 and my app was built with .net 4.0 and wasn't using it by default.
I rebuilt with .net 4.5, setting security protocol and using HttpClient. That solved the issue.


Friday, June 30, 2017 3:37 AM

In .NET, you would use one of the following objects.

HttpWebRequest/HttpWebResponse

WebClient

HttpClient (available from .NET 4.5 on)

You can post to the Web service forum for further help.

https://forums.asp.net/28.aspx/1?WCF+ASMX+and+other+Web+Services


Friday, June 30, 2017 2:13 PM | 1 vote

You're trying to make an OAuth request. Use WebClient to do this if you want a built in solution. For REST calls you probably should consider using a rest client likes RestSharp instead.

var client = new WebClient();

var url = @"http://someurl";
var creds = new OAuthCredentials();

//Convert your data to JSON using a JSON converter, using JSON.NET here            
var body = JsonConvert.SerializeObject(creds);

client.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
client.UploadStringTaskAsync(url, body);

[DataContract]
public class OAuthCredentials
{
    [DataMember]
    public string grant_type { get; set; }
    [DataMember]
    public string client_id { get; set; }
    [DataMember]
    public string client_secret { get; set; }
    [DataMember]
    public string username { get; set; }
    [DataMember]
    public string password { get; set; }
}

Note that in your code you are trying to combine the generation of the credentials with their usage. With OAuth you first have to send the credentials to the OAuth provider (which is what your CURL request is trying to do). If that call is successful then you get back a bearer token that you then insert as a header in subsequent calls to the API.

I'd recommend you take a look at Postman. Postman is designed to call REST APIs like you're trying to do. The best part about it though is that once you have a test call working it can show you the code that is needed to do it including CURL and C#. I'd recommend you ultimately get the code from there.

Michael Taylor
Http://www.michaeltaylorp3.net


Friday, June 30, 2017 6:10 PM

Hi Michael
I see your point about credentials but I tried putting them into RequestStream and had the same "bad request" error.

I tried WebClient and got the same error.

It did work from Postman but the code is in C#(RestSharp).
Would be nice to have it without referencing additional third party libraries.

Below is the code I got, you think maybe there is a header to add or something?

Thank you for you help.

var client = new RestClient("https://someurl");
            var request = new RestRequest(Method.POST);
            request.AddHeader("postman-token", "dff35016-1fe1-5f4f-bc4b-6b172c21ff02");
            request.AddHeader("cache-control", "no-cache");
            request.AddHeader("contenttype", "application/x-www-form-urlencoded");
            request.AddHeader("content-type", "multipart/form-data; boundary=WebKitFormBoundary7MA4YWxkTrZu0gW");
            request.AddParameter("multipart/form-data; boundary=WebKitFormBoundary7MA4YWxkTrZu0gW", "WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Dis-data; name=\"grant_type\"\r\n\r\npassword\r\nWebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Dis-data; name=\"client_id\"\r\n\r\nclient_id_value\r\nWebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Dis-data; name=\"client_secret\"\r\n\r\nsecret_value\r\nWebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Dis-data; name=\"username\"\r\n\r\nname\r\nWebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Dis-data; name=\"password\"\r\n\r\npwd\r\nWebKitFormBoundary7MA4YWxkTrZu0gW--", ParameterType.RequestBody);
            IRestResponse response = client.Execute(request);

Friday, June 30, 2017 6:51 PM

You're adding that stuff to the header. That is wrong. The data is in the body. That is what the -D stuff on the CURL command is.

The code I posted correctly puts data into the content body where it belongs for a POST request. The content type is also set properly. The UploadString call correctly passes the data as JSON in the POST request to the server. All this lines up with your CURL command accept the CURL command didn't appear to be setting any headers. What error did you get when you used the code I posted? 

In your posted code you're passing a multipart form. Why are you doing this? That doesn't line up with the CURL command or how OAuth is done. Can you post the details of the Postman request that you're sending?


Friday, June 30, 2017 7:15 PM

What I meant was that I also tried, no credentials in the header but
"grant_type=password&client_id=client_id_value&client_secret=client_secret_value&username=name&password=pwd"
and it didn't work.

When I run this code
var client = new WebClient();
var url = @"<https://someurl>";
var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
var body = ser.Serialize(m_creds);
client.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
client.UploadString(new Uri(url), body);

where body is
{"grant_type":"password","client_id":"whatever","client_secret":"whatever","username":"whatever","password":"whatever"}

I am getting "The remote server returned an error: (400) Bad Request."
   at System.Net.WebClient.UploadDataInternal(Uri address, String method, Byte[] data, WebRequest& request)
   at System.Net.WebClient.UploadString(Uri address, String method, String data)
   at System.Net.WebClient.UploadString(Uri address, String data)

Why I am doing multipart form?
I don't really know what I am doing but I suspect this is because "form-data" radio button was selected.
but if I select "x-www-form-urlencoded" I get
{
    "error": "unsupported_grant_type",
    "error_description": "grant type not supported"
}

sorry, can't find where to view details of the Postman request

Thanks!


Friday, June 30, 2017 7:32 PM

Does the original CURL command you posted work? sorry, but for URL form values JSON isn't the value you'd send in the body. Using Postman this is the form body that would be correct for the encoding you mentioned.

grant_type:password
client_id:client_id_value
client_secret:client_secret_value
username:name
password:pwd

Send that as the body in the UploadData call and see what happens.


Monday, July 3, 2017 1:52 PM

Hi Michael
sorry I am a bit lost so I'll take it step by step.

Does the original CURL command you posted work?
 Yes, original CURL command works.
 
for URL form values JSON isn't the value you'd send in the body
 ok

Using Postman this is the form body that would be correct for the encoding you mentioned.
 I understand Postman is useless to me then?

Send that as the body in the UploadData call and see what happens
 grant_type:password
 client_id:client_id_value
 client_secret:client_secret_value
 username:name
 password:pwd

This is exactly what I was doing before and getting  "The remote server returned an error: (400) Bad Request."
(obviously values I am posting here are not what I am sending, so "client_id_value" or "whatever" is not important )

  var client = new WebClient();
  var url = @"<https://someurl>";
  var ser = new System.Web.Script.Serialization.JavaScriptSerializer();
  var body = ser.Serialize(m_creds);
  client.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
  client.UploadString(new Uri(url), body);

  where body is
  {"grant_type":"password","client_id":"whatever","client_secret":"whatever","username":"whatever","password":"whatever"}
 
 
Thank you for your help.