HttpRequest httpRequest = new HttpRequest();
RequestParams reqParams = new RequestParams { };
httpRequest.IgnoreProtocolErrors = true;
reqParams["data"] = "{\"path\": \"/Prime_Numbers.txt\"}";
httpRequest.AddHeader("Authorization", " Bearer MYKEY");
httpRequest.AddHeader("Content-Type", "application/json");
Console.WriteLine(httpRequest.Post("https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings", reqParams).ToString());
Im getting the following error: Error in call to API function "sharing/create_shared_link_with_settings": request body: could not decode input as JSON. I am using the dropbox api.
I saw the following: https://github.com/csharp-leaf/Leaf.xNet/issues/66 (Someone had a similar issue, but this fix did not work)
When you are using RequestParams that means Context-Type: application/x-www-form-urlencoded.
You can't set Content-Type via .AddHeader(), use argument for .Post(url, json, contentType) method like this:
HttpRequest httpRequest = new HttpRequest();
httpRequest.AddHeader("Authorization", " Bearer MYKEY");
string url = "https://api.dropboxapi.com/2/sharing/create_shared_link_with_settings";
string jsonData = "{\"path\": \"/Prime_Numbers.txt\"}";
string response = httpRequest.Post(url, jsonData, "application/json").ToString();
Console.WriteLine(response);
Related
I've got a working Java method that uses java.net.HttpURLConnection that I should re-implement in C# using the .NET HttpClient.
Java method:
public static String getMyThingAPIToken() throws IOException{
URL apiURL = new URL("https://myThingAPI/token");
HttpURLConnection apiConnection = (HttpURLConnection) apiURL.openConnection();
apiConnection.setRequestMethod("POST");
apiConnection.setDoOutput(true);
String apiBodyString = "myThingAPI login id and secret key";
byte[] apiBody = apiBodyString.getBytes(StandardCharsets.UTF_8);
OutputStream apiBodyStream = apiConnection.getOutputStream();
apiBodyStream.write(apiBody);
StringBuffer apiResponseBuffer;
try (BufferedReader in = new BufferedReader(new InputStreamReader(apiConnection.getInputStream()))){
String inputline;
apiResponseBuffer = new StringBuffer();
while((inputline = in.readLine()) != null) {
apiResponseBuffer.append(inputline);
}
}
}
So far, my C# looks like below, and you'll notice that this early form of my implementation does not interpret the response. Nor does it have a string return type required for the token string.
This is because when I test it, the response has:
StatusCode: 400
ReasonPhrase: 'Bad Request'
So something in my apiBody byte array or use of PostAsync must be different to what the Java method does, but I cannot work out what it could be.
public async static Task<HttpResponseMessage> getMyThingAPIToken(HttpClient client)
{
var apiURI = new Uri("https://myThingAPI/token");
string apiBodystring = "myThingAPI login id and secret key";
byte[] apiBody = System.Text.Encoding.UTF8.GetBytes(apiBodystring);
var response = await client.PostAsync(apiURI, new ByteArrayContent(apiBody));
return response;
}
The Java code doesn't specify a type which means that by default the request uses application/x-www-form-urlencoded. This is used for FORM POST requests.
The default content type for ByteArrayContent on the other hand is application/octet-stream while for StringContent it's text/plain.
FORM content is used through the FormUrlEncoodedContent class which can accept any Dictionary<string,string> as payload.
The input in the question is not in a x-www-form-urlencoded form so either it's not the real content or the API is misusing content types.
Assuming the API accepts proper x-www-form-urlencoded content, the following should work:
var data=new Dictionary<string,string>{
["login"]=....,
["secret"]=.....,
["someOtherField"]=....
};
var content= new FormUrlEncodedContent(data);
var response=await client.PostAsync(apiURI,content);
To send any text using application/x-www-form-urlencoded, we need to specify the content type in StringContent's constructor:
var contentType="application/x-www-form-urlencoded";
var content= new StringContent(apiBodyString, Encoding.UTF8,contentType);
var response=await client.PostAsync(apiURI,content);
Can you try using following code:
client.BaseAddress = new Uri("https://myThingAPI/");
var message = new HttpRequestMessage(HttpMethod.Post, "/token");
// Add your login id and secret key here with the format you want to send
message.Content = new StringContent(string.Format("userName={0}&password={1}", UserName, Password));
var result = await client.SendAsync(message);
return result;
Below is code snippet for POST api call where I am stuck with error:
Bad request
After searching the web, I understand that you get this error when you don't follow proper payload syntax or pass proper payload data while making a post api call.
Here are different ways that I tried so far but unfortunately none work.
// payload data's class represantation,
public class DNCAddressInfo
{
[JsonProperty("dncAddress")]
public string DNCAddress { get; set; }
[JsonProperty("checkForPhoneRejection")]
public bool CheckForPhoneRejection { get; set; }
[JsonProperty("checkForPhoneFormats")]
public bool CheckForPhoneFormats { get; set; }
}
First try:
DNCAddressInfo dncObj = GetPayloadData();
string payload = JsonConvert.SerializeObject(dncObj);
var content = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsJsonAsync(url, content).ConfigureAwait(false); // response: error code: 400 , bad request
Second try:
DNCAddressInfo dncObj = GetPayloadData();
JObject jsonObject = new JObject
{
["dncAddress"] = JsonConvert.SerializeObject(dncObj.DNCAddress),
["checkForPhoneRejection"] = JsonConvert.SerializeObject(dncObj.CheckForPhoneRejection),
["checkForPhoneFormats"] = JsonConvert.SerializeObject(dncObj.CheckForPhoneFormats)
};
var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsJsonAsync(url, content).ConfigureAwait(false);// response: error code: 400 , bad request
Third try:
string payload = "{\"dncAddress\": \"91#1231123\", \"checkForPhoneRejection\": false, \"checkForPhoneFormats\": false}"; // sample payload data taken from api providers document
var content = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsJsonAsync(url, content).ConfigureAwait(false); // response: error code: 400 , bad request
All three approaches resulted in same error,
StatusCode: 400, ReasonPhrase: '400'
Request header is ,
Headers = {Authorization: Basic XXXXX;
Accept: application/json
X-Requested-With: rest
Cache-Control: no-cache
}
Response from Postman looks all fine. Here is snapshot of same.
Is there anything I am doing wrong here or missing anything?
With PostJsonAsync method, you don't need to manually serialize an object to json, just pass it as it is:
DNCAddressInfo dncObj = GetPayloadData();
HttpResponseMessage response = await _client.PostAsJsonAsync(url, dncObj).ConfigureAwait(false);
or you can use newer HttpClient.PostAsync:
DNCAddressInfo dncObj = GetPayloadData();
string payload = JsonConvert.SerializeObject(dncObj);
var content = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsync(url, content).ConfigureAwait(false);
References: HttpClient.PostAsync Method, HttpClientExtensions.PostAsJsonAsync Method
"PostAsJsonAsync" method serializes data inside. When you pass "StringContent" to this method then HttpClient serializes "StringContent" to Json and sends wrong data.
Try to use "PostAsync" instead of "PostAsJsonAsync".
I have fetch channel history in my .Net Web API.
The slack reference https://api.slack.com/methods/channels.history it states that we need to post the request.
Please if someone could help me with the code.
Part of Code I have implemented:
#region create json payload to send to slack
GetLatestMessage payload = new GetLatestMessage()
{
channel = "###",//value.channel_name,
token = "############################"//added the token i have generated
// user_name = value.user_name,
//text = value.text
};
#endregion
string payloadJson = JsonConvert.SerializeObject(payload);
using (WebClient client = new WebClient())
{
NameValueCollection data = new NameValueCollection();
data["payload"] = payloadJson;
var response = client.UploadValues("https://slack.com/api/channels.history", "POST", data);
//The response text is usually "ok"
string responseText = _encoding.GetString(response);
LogFileWriter("response=" + responseText);
return Request.CreateResponse(HttpStatusCode.OK);
}
I figured out the issue I was facing.I was trying to sent the post json data in to Slack url. However The Slack Web API doesn't accept JSON data.Now when I post data using standard HTTP form attributes it accepts and returns proper response.
New code:
var response = client.UploadValues("https://slack.com/api/channels.history", "POST", new NameValueCollection() {
{"token","###################"},
{"channel","######"}});
//The response text is usually "ok"
string responseText = _encoding.GetString(response);
LogFileWriter("response=" + responseText);
return Request.CreateResponse(HttpStatusCode.OK);
}
I've built my backend in rails.
My email address is "sample#zmail.com" and it's already registered. The password is "28902890" here
After giving the following command in terminal
curl -v -H 'Content-Type: application/json' -H 'Accept: application/json' -X POST https://auth-agdit.herokuapp.com/api/v1/sessions -d "{\"user\":{\"email\":\"sample#zmail\",\"password\":\"28902890\"}}"
I get this response from my backend,
{"success":true,"info":"Logged in :) ","data":{"authentication_token":"iexGFwJ6HwERQZ3wJ4NG"}}
Now I need to get this data from my Android app.
I can get json by using WebClient().downloadString() method for simple json where authentication is not needed and the request method is GET.
Now I need to get the output Json for POST method.
How can I accomplish that?
There are several methods of doing this. You could use the Xamarin component called RestSharp. This will provide you with easy methods of interfacing with your backend.
var request = new RestRequest("resource/{id}", Method.POST);
request.AddParameter("name", "value"); // adds to POST or URL querystring based on Method
request.AddUrlSegment("id", 123); // replaces matching token in request.Resource
// add parameters for all properties on an object
request.AddObject(object);
// execute the request
RestResponse response = client.Execute(request);
If you do want to simply use the WebClient class provided by the BCL you can use the WebClient.UploadString(string, string) method like so:
using (WebClient client = new WebClient())
{
string json = "{\"user\":{\"email\":\"sample#zmail\",\"password\":\"28902890\"}}";
client.UploadString("https://example.com/api/v1/sessions, json);
}
If you need more control over the request (such as setting accept headers, etc.) then you can use HttpRequest, see this question for an example of that.
This is how I did it:
WebClient wc = new WebClient();
string baseSiteString = wc.DownloadString("https://auth-agdit.herokuapp.com");
string csrfToken = Regex.Match(baseSiteString, "<meta name=\"csrf-token\" content=\"(.*?)\" />").Groups[1].Value;
string cookie = wc.ResponseHeaders[HttpResponseHeader.SetCookie];
Console.WriteLine("CSRF Token: {0}", csrfToken);
Console.WriteLine("Cookie: {0}", cookie);
wc.Headers.Add(HttpRequestHeader.Cookie, cookie);
wc.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
wc.Headers.Add(HttpRequestHeader.Accept, "application/json, text/javascript, */*; q=0.01");
wc.Headers.Add("X-CSRF-Token", csrfToken);
wc.Headers.Add("X-Requested-With", "XMLHttpRequest");
string dataString = #"{""user"":{""email"":""email_here"",""password"":""password_here""}}";
// string dataString = #"{""user"":{""email"":"""+uEmail+#""",""password"":"""+uPassword+#"""}}";
byte[] dataBytes = Encoding.UTF8.GetBytes(dataString);
byte[] responseBytes = wc.UploadData(new Uri("https://auth-agdit.herokuapp.com/api/v1/sessions.json"), "POST", dataBytes);
string responseString = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine(responseString);
Try with this code:
Uri address = new Uri("http://example.com/insert.php");
NameValueCollection nameValueCollection = new NameValueCollection();
nameValueCollection["Name"] = "string-input";
var webClient = new WebClient();
webClient.UploadValuesAsync(address, "POST", nameValueCollection);
The following is the code sample provided by msdn for obtaining an SWT token from azure ACS (Access Control Service):
private static string GetTokenFromACS(string scope)
{
string wrapPassword = pwd;
string wrapUsername = uid;
// request a token from ACS
WebClient client = new WebClient();
client.BaseAddress = string.Format(
"https://{0}.{1}", serviceNamespace, acsHostUrl);
NameValueCollection values = new NameValueCollection();
values.Add("wrap_name", wrapUsername);
values.Add("wrap_password", wrapPassword);
values.Add("wrap_scope", scope);
byte[] responseBytes = client.UploadValues("WRAPv0.9/", "POST", values);
string response = Encoding.UTF8.GetString(responseBytes);
Console.WriteLine("\nreceived token from ACS: {0}\n", response);
return HttpUtility.UrlDecode(
response
.Split('&')
.Single(value => value.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase))
.Split('=')[1]);
}
I am trying to replicate the code using RestSharp:
var request = new RestRequest("WRAPv0.9", Method.POST);
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddParameter("wrap_name", uid, ParameterType.RequestBody);
request.AddParameter("wrap_password", pwd, ParameterType.RequestBody);
request.AddParameter("wrap_scope", realm, ParameterType.RequestBody);
RestClient client = new RestClient(
string.Format(#"https://{0}.{1}", serviceNamespace, acsHostUrl));
client.ExecuteAsync(request, Callback);
I tried other variations of the above code but to no avail. I keep recieving a 415 error stating that:
415 Unsupported Media Type T8000 Content-Type 'text/plain' is not
supported. The request content type must be
'application/x-www-form-urlencoded'.
I am not a Fiddler expert but with my limited experience with it I was not able to inspect my outgoing http request because it is encrypted.
I would appreciate advice on solving the issue.
You can try to leave out the AddHeader method call and instead set the Content-Type as the first AddParameter.
The issue is described here.