How to make simple Json Post in Asp.net with parameter [closed] - c#

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I Have logic App running in Azure that connect to on premise database , i already succesfull to Post data via xamarin forms but now to make the logic apps link more safety i want to create Web Api that handle the post request. And when I am try to test it via postman it keep getting this message
"Message": "The requested resource does not support http method 'POST'."
I already make post code in the Asp.net and I don't know why its said that my Asp.net don't support html method Post ? here is my full Post Source Code
string sUrl = "My Logic Apps Link";
string sContentType = "application/json"; // or application/xml
// POST api/<controller>
public async void Post(string param1, string param2, string param3)
{
JObject oJsonObject = new JObject();
oJsonObject.Add("param1", param1);
oJsonObject.Add("param2", param2);
oJsonObject.Add("param3", param3);
HttpClient oHttpClient = new HttpClient();
var oTaskPostAsync = await oHttpClient.PostAsync(sUrl, new StringContent(oJsonObject.ToString(), Encoding.UTF8, sContentType));
if (oTaskPostAsync.IsSuccessStatusCode)
{
string content = await oTaskPostAsync.Content.ReadAsStringAsync();
content.ToString();
}
}
please review my code and tell me where is my mistake , because when im try this in xamarin.forms it works and here is the postman body request
{
"param1":"value",
"param2":"value",
"param3":"value"
}
i try with get method and its return value with the parameter hard coded
[Route("postdata")]
// GET api/Post
public string Get()
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://xxx-xx.southeastasia.logic.azure.com");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new
{
param1 = "value",
param2 = "value",
param3 = "value"
});
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
but i dont know why the post mode always get error message
// GET api/Post
public string Post(string type, string type1, string email )
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://xxxx-xx.southeastasia.logic.azure.com");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new
{
param1 = type,
param2 = type1,
param3 = email
});
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
Why that happen ? I'm still very very new in asp.net, can you tell me where is the part that I'm wrong thanks

You need to add the attribute to the action:
[HttpPost]
public async void Post(string param1, string param2, string param3)
And if you sending the parameter via body you need to tell your action:
[HttpPost]
public async void Post([FromBody]YourClass params)
Take a look at this article: https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-1

Related

C# code to get data from Endpoint with username and private key [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have this endpoint which i want to get data from . This endpoint has certain method to get data and post data . Now what happens is i have the username and private key when i need to get data from the endpoint i will need this to be posted so that it return a url with hash id on it when i can run it on the browser to see the data returned . Below is an example of that url:
https://endpoint/api/product/associatedproducst?username=myusername&version=2&hash=69865ce2329d1d0904498f64d94e8392
Below is the code i have :
public string Getproduct(string endpoint, string username, string privatekey)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://endpoint");
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Headers.Add("username:" + username);
httpWebRequest.Headers.Add("privatekey:" + privatekey);
//pass basic authentication credentials
httpWebRequest.Credentials = new NetworkCredential("myuserid", "myid");
httpWebRequest.Method = "GET";
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
return responseText;
}
}
I need some help and guidance on how i can continue from the code above so that i can generate those url and hash id on it so that i can read the data and display it as well .
Please note this endpoint has methods to get certain data how can i call those methods so that correct url can return from it to get data.
Try using an HttpClient. I looked at the API and came up with the solution. The API mentions that you should never send the private key. The private key is used to generate the HASH you are sending through the query string. For the private function below I am just guessing your use case.
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
var client = new HttpClient();
public async string Getproduct(string endpoint, string username, string privateKey)
{
var queryString = string.Format("?username={0}&version=2", username).ToUpper();
var hash = GenerateHash(privateKey, queryString);
client.DefaultRequestHeaders.Accept.Clear();
//client.BaseAddress = new Uri(baseUri);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var url = string.Format("{0}{1}&hash={2}",endpoint, queryString, hash);
using (HttpResponseMessage response = await client.GetAsync(url))
{
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
return json;
}
else
{
var statusCode = response.StatusCode;
//handle code here.
}
}
}
public async void PostProduct(string endpoint, string username, string privateKey)
{
var queryString = string.Format("?username={0}&version=2", username).ToUpper();
var hash = GenerateHash(privateKey, queryString);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
var url = string.Format("{0}{1}&hash={2}", endpoint, queryString, hash);
var dict = new Dictionary<string, string>();
dict.Add("hotel_id ", "1");
dict.Add("room_id ", "2");
var content = new FormUrlEncodedContent(dict);
using (HttpResponseMessage response = await client.PostAsync(url, content))
{
if (response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
}
else
{
var statusCode = response.StatusCode;
//handle code here.
}
}
}
private string GenerateHash(string privateKey, string queryString)
{
var md5 = MD5.Create();
string salt = queryString;
byte[] bytes = md5.ComputeHash(Encoding.ASCII.GetBytes(salt + privateKey));
return BitConverter.ToString(bytes);
}

Coinbase API returns 401 for POST

I'm trying to use Coinbase's API to sell crypto currency, and I keep getting 401 errors. The below code works for all of the GET methods I've tried so far, but I can't figure out where I'm going wrong with the POST.
private static string GetWebResponse(string url, string command, string path, string body)
{
var timeStamp = EpochSeconds;
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = command;
request.ContentType = "application/json";
request.Headers.Add("CB-VERSION", VersionDate);
request.Headers.Add("CB-ACCESS-KEY", ApiKey);
request.Headers.Add("CB-ACCESS-SIGN", GetAccessSign(timeStamp, command, path, body));
request.Headers.Add("CB-ACCESS-TIMESTAMP", timeStamp);
if (command == "POST")
{
using (var streamWriter = new StreamWriter(request.GetRequestStream()))
{
streamWriter.Write(body);
streamWriter.Flush();
streamWriter.Close();
}
}
var response = (HttpWebResponse)request.GetResponse();
using (var reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII))
{
return reader.ReadToEnd();
}
}
private static string GetAccessSign(string timestamp, string command, string path, string body)
{
var hmacKey = Encoding.UTF8.GetBytes(ApiSecret);
string data = timestamp + command + path + body;
using (var signatureStream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
{
return new HMACSHA256(hmacKey).ComputeHash(signatureStream).Aggregate(new StringBuilder(), (sb, b) => sb.AppendFormat("{0:x2}", b), sb => sb.ToString());
}
}
I figure something is wrong with the body of the POST request, but it looks right to me.
EDIT:
I'm going to show how the body is formed for clarification...
var body = JsonConvert.SerializeObject(
new
{
commit = "false",
amount = Math.Round(sellAmount, 8).ToString(),
currency = "BTC",
payment_method = fiatWalletId
});
EDIT 2:
I tried all the same stuff as before, but using RestSharp, and it returns a more specific error:
{\"errors\":[{\"id\":\"authentication_error\",\"message\":\"invalid signature\"}]}
EDIT 3:
This API key is set up for all permissions / scopes, including the ones I need for this request:
wallet:accounts:create
wallet:accounts:delete
wallet:accounts:read
wallet:accounts:update
wallet:addresses:create
wallet:addresses:read
wallet:buys:create
wallet:buys:read
wallet:checkouts:create
wallet:checkouts:read
wallet:contacts:read
wallet:deposits:create
wallet:deposits:read
wallet:notifications:read
wallet:orders:create
wallet:orders:read
wallet:orders:refund
wallet:payment-methods:delete
wallet:payment-methods:limits
wallet:payment-methods:read
wallet:sells:create
wallet:sells:read
wallet:transactions:read
wallet:transactions:request
wallet:transactions:send
wallet:transactions:transfer
wallet:user:email
wallet:user:read
wallet:user:update
wallet:withdrawals:create
wallet:withdrawals:read
The solution for me was that I forgot to put /v2 (/v2 + some path) in the path part of the signature and the signature was bad, the response was misleading though saying unauthorized.

Getting 404 error only when using .NET framework

I'm trying to create a version in JIRA for a specific project.
I'm able to do the process via Postman by building my requests manually, but it fails with a 404 when creating the version record via .NET.
I'm assuming .NET adds pesky parameters to the request that Postman doesn't do.
The weird thing is that the authentication call works, but the the version creation fails.
Here's the helper I wrote:
public class JIRA
{
private string AuthToken { get; set; }
private const string c_JIRAUrl = "https://org.atlassian.net";
private const string c_LoginUrl = c_JIRAUrl + "/rest/auth/1/session";
private const string c_CreateVersionUrl = c_JIRAUrl + "/rest/api/2/version";
public JIRA()
{
//this works...
var authResponse = ExecuteRequest(c_LoginUrl, "POST", new
{
username = "login",
password = "password"
});
AuthToken = authResponse["session"]["value"].ToString();
}
public void CreateVersion(string name, string projectKey, ProjectEnvironment environment)
{
//lets hardcode the same data I use in Postman for testing purposes...
var createVersionResponse = ExecuteRequest(c_CreateVersionUrl, "POST", new
{
description = "An excellent version",
name = "1.1.2",
archived = false,
released = false,
project = "TEST"
});
}
private JObject ExecuteRequest(string url, string method, object data)
{
HttpWebResponse response;
var jsonDataString = JsonConvert.SerializeObject(data);
byte[] dataBytes = Encoding.Default.GetBytes(jsonDataString);
var responseText = string.Empty;
var wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "application/json";
if (!string.IsNullOrEmpty(AuthToken))
wr.Headers.Add(HttpRequestHeader.Authorization, $"Bearer {AuthToken}");
wr.Method = method;
wr.ContentLength = dataBytes.Length;
wr.Accept = "application/json";
using (var webStream = wr.GetRequestStream())
{
webStream.Write(dataBytes, 0, dataBytes.Length);
response = (HttpWebResponse)wr.GetResponse();
}
using (var sr = new StreamReader(response.GetResponseStream()))
{
responseText = sr.ReadToEnd();
}
return JObject.Parse(responseText);
}
}
The CreateVersion method always fails with a 404.
As I've said, doing the same (retrieving the token, creating the version) all works in Postman.
Any ideas what's going on ?
Thanks.
Apparently, when retrieving the token (/rest/auth/1/session) the response contains cookies that POSTMAN was sending back in the 2nd request (creating the version). I had to fire up Fiddler to find out it was doing so because its UI was not saying so.
My .NET client was not doing so. When making it do so, it works.
I'm a little miffed that a REST service expects cookies...

Error in json post request for mailchimp api

I am trying to create a wrapper for:
this mailchimp method using C#.Net
I understand that there are already .Net wrappers available. I am using Mailchimp.Net by Dan Esparza. Method in the wrapper class is giving exception for the api method mentioned above.It is throwing internal server exception (500) which I am not sure why, so I decided to create my own wrapper for the particular method. I have following code:
private void CreateGrouping(string apiKey, string listId,string groupName,string groupValue)
{
string url = "https://us9.api.mailchimp.com/2.0/lists/interest-grouping-add";
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
List<string> values = new List<string>();
values.Add(groupValue);
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = new JavaScriptSerializer().Serialize(new
{
apiKey = apiKey,
id = listId,
name = groupName,
type="radio",
groups = values
});
streamWriter.Write(json);
}
var response = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
But on execution of var response = (HttpWebResponse)httpWebRequest.GetResponse(); is throwing same exception - internal server error (500).
It might be that I am passing data in wrong way ? Can someone please help me in finding out what am I missing here ?
As I suspected I was passing the data in wrong way: apiKey has to be apikey (k was in caps)
string json = new JavaScriptSerializer().Serialize(new
{
apikey = apiKey,
id = listId,
name = groupName,
type="radio",
groups = values
});
Other than this, I added:
streamWriter.Flush();
streamWriter.Close();
It might help someone save sometime.

C# Http.Response Stream Returns Empty String With application/json Content Type

Having a simple C# unit test:
[TestMethod]
public void JsonPostTest()
{
string testUri1 = "http://localhost:1293/Test/StreamDebug";
string testUri2 = "http://localhost:1293/Test/StreamDebug2?someParameter=abc";
string sampleJson = #"
{
""ID"": 663941764,
""MessageID"": ""067eb623-7580-4d82-bb5c-f5d7dfa69b1e""
}";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(testUri1);
EmailConfig config = GetTestConfigLive();
// Add postmark headers
request.Accept = "application/json";
request.ContentType = "application/json";
request.Method = "POST";
using (var outStream = new StreamWriter(request.GetRequestStream()))
{
outStream.Write(sampleJson);
}
// Get response
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
string resultText = "";
using (var reader = new StreamReader(response.GetResponseStream()))
{
resultText = reader.ReadToEnd();
}
Assert.Inconclusive();
}
And a simple set of MVC actions to consume and echo posted data back to the unit test (Notice that the code in both actions is identical):
[HttpPost]
[ValidateInput(false)]
public ActionResult StreamDebug()
{
string postbody = "";
using (StreamReader reader = new StreamReader(Request.InputStream, Encoding.UTF8))
{
postbody = reader.ReadToEnd();
}
return this.Content(postbody);
}
[HttpPost]
[ValidateInput(false)]
public ActionResult StreamDebug2(string someParameter)
{
string postbody = "";
using (StreamReader reader = new StreamReader(Request.InputStream, Encoding.UTF8))
{
postbody = reader.ReadToEnd();
}
return this.Content(postbody);
}
If I post to the first action I get a string containing the posted json, if I post to the second action I get an empty string.
To make matters more interesting, if I change the content type in the unit test to "text/plain", both actions return the expected values.
Can anyone shed any light on why this might be happening?
Its also worth noting that the request length on the both actions under both sets of circumstances seems to be of the right length.
Further environmental information:
Unit test is in a separate MS test project.
Actions are in a empty MVC 4.0 project (Net 4.0).
It is possible that somewhere in the request pipeline Request.InputStream was already read. In this case its position is already at the end, and of course ReadToEnd reads nothing and returns empty string. This is the root of the problem in our case. Resetting the position fixes the problem:
[HttpPost]
[ValidateInput(false)]
public ActionResult StreamDebug2(string someParameter)
{
string postbody = "";
Request.InputStream.Position = 0;
using (StreamReader reader = new StreamReader(Request.InputStream, Encoding.UTF8))
{
postbody = reader.ReadToEnd();
}
return this.Content(postbody);
}
Update. After a little bit of digging into sources I also found why the position was shifted. It turns out that Request.InputStream is used in JsonValueProviderFactory in the following manner:
// System.Web.Mvc.JsonValueProviderFactory
private static object GetDeserializedObject(ControllerContext controllerContext)
{
if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))
{
return null;
}
StreamReader streamReader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
string text = streamReader.ReadToEnd();
if (string.IsNullOrEmpty(text))
{
return null;
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
return javaScriptSerializer.DeserializeObject(text);
}
This method is called by ControllerActionInvoker to retrieve values from request and bind them to action parameters. Note that this is the only place where Request.InputStream is used through all the MVC.
Therefore if content type of the request is json, the method above is called, input stream gets shifted and attempt to read it yet again without resetting the position fails. However when content type is a plain text, MVC does not try to read the request using json deserialization, input stream is not read before the call in controller and everything works as expected.

Categories