Why is my HTTP POST Body content received/processed as NULL? - c#

I want to be able to receive the Body content of a POST request inside the POST function definition in the REST API.
I have a client code that converts a C# object into JSON and then wraps it in a HTTP StringContent. This payload is then sent via a HTTP Post request to the URL. However the Post method in API always returns NULL when I try returning the received string.
Client:
public async void Register_Clicked(object sender, EventArgs e) // When user enters the Register button
{
Sjson = JsonConvert.SerializeObject(signup);
var httpContent = new StringContent(Sjson);
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://apiname.azurewebsites.net");
var response = await client.PostAsync("api/values", httpContent);
var responseContent = await response.Content.ReadAsStringAsync();
StatusLabel.Text = responseContent; //To display response in client
}
}
API POST Definition:
[SwaggerOperation("Create")]
[SwaggerResponse(HttpStatusCode.Created)]
public string Post([FromBody]string signup)
{
return signup;
}
I want the clients input back as a response to be displayed in the client (StatusLabel.Text). However all I receive is NULL. Kindly guide me in the right direction.

I have prepared a simple example on how you can retrieve your Result from your Task:
async Task<string> GetResponseString(SigupModel signup)
{
Sjson = JsonConvert.SerializeObject(signup);
var httpContent = new StringContent(Sjson);
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("https://apiname.azurewebsites.net");
var response = await client.PostAsync("api/values", httpContent);
var responseContent = await response.Content.ReadAsStringAsync();
}
return responseContent;
}
And you can call this as:
Task<string> result = GetResponseString(signup);
var finalResult = result.Result;
StatusLabel.Text = finalResult; //To display response in client
If you are not using async keyword, then you can call get your Result as:
var responseContent = response.Content.ReadAsStringAsync().Result;
EDIT
Basically you would have to POST your signup model to your API Controller. Use SigupModel signup as a parameter if you would like. Then whatever processing you are doing in the API, the final result in a string. Now this string can either be a null, empty or have a value. When you get this value in your client, you would have do the following:
var responseContent = await response.Content.ReadAsStringAsync();
var message = JsonConvert.DeserializeObject<string>(responseContent);
Here you will get your message a string and then you can set it as: StatusLabel.Text = message ;

Related

Send a JSON request to another web site from C# code behind in an ASP.NET MVC project

I'm working with ASP.NET MVC (backend being C#) and I'm trying to send a json that would look like this :
{
"store_id": "store3",
"api_token": "yesguy",
"checkout_id": "UniqueNumber",
"txn_total": "10.00",
"environment": "qa",
"action": "preload"
}
to another web site, suppose it's something like:
https://TestGate.paimon.com/chkt/request/request.php
Through some research I found this :
Send json to another server using asp.net core mvc c#
Looks good but I'm not working in core, my project is just normal ASP.NET MVC. I don't know how to use json functions to send it to a web site.
Here is what I tried (updated after inspired by Liad Dadon answer) :
public ActionResult Index(int idInsc)
{
INSC_Inscription insc = GetMainModelInfos(idinsc);
JsonModel jm = new JsonModel();
jm.store_id = "store2";
jm.api_token = "yesguy";
jm.checkout_id = "uniqueId";
jm.txn_total = "123.00";
jm.environment = "qa";
jm.action = "preload";
var jsonObject = JsonConvert.SerializeObject(jm);
var url = "https://gatewayt.whatever.com/chkt/request/request.php";
HttpClient client = new HttpClient();
var content = new StringContent(jsonObject, System.Text.Encoding.UTF8, "application/json");
System.Threading.Tasks.Task<HttpResponseMessage> res = client.PostAsync(url, content);
insc.response = res.Result; // This cause an exeption
return View(insc);
}
When ths Json is posted correctly, the other web site will answer me with is own Json :
{
"response" :
{
"success": "true",
"ticket": "Another_Long_And_Unique_Id_From_The_Other_Web_Site"
}
}
What I need to do is retreive this Json answer, once I have it, the rest is piece of cake.
Infos :
After the PostAsync function, var res contains this :
It looks like you might not be correctly handling an asynchronous task — the WaitingForActivation message you’re seeing, rather than being a response from our API, is in fact the status of your task.
The task is waiting to be activated and scheduled internally by the .NET Framework infrastructure.
It seems you might need to await⁽²⁾ the task to ensure it completes or access the response with await client.PostAsync(url, content);. for adding await you need to add async to controller⁽¹⁾ action.
public async Task<ActionResult> Index(int idInsc) //Change here [1]
{
INSC_Inscription insc = GetMainModelInfos(idinsc);
JsonModel jm = new JsonModel();
jm.store_id = "store2";
jm.api_token = "yesguy";
jm.checkout_id = "uniqueId";
jm.txn_total = "123.00";
jm.environment = "qa";
jm.action = "preload";
var jsonObject = JsonConvert.SerializeObject(jm);
var url = "https://gatewayt.whatever.com/chkt/request/request.php";
HttpClient client = new HttpClient();
var content = new StringContent(jsonObject, System.Text.Encoding.UTF8, "application/json");
System.Threading.Tasks.Task<HttpResponseMessage> res = await client.PostAsync(url, content); //Change here [2]
insc.response = res.Result; // This cause an exeption
return View(insc);
}
This is how I would post a JSON object to somewhere using Newtonsoft.Json package, HttpClient and StringContent classes:
using Newtonsoft.Json;
var object = new Model
{
//your properties
}
var jsonObject = JsonConvert.SerializeObject(object);
var url = "http://yoururl.com/endpoint"; //<- your url here
try
{
using HttpClient client = new();
var content = new StringContent(jsonObject , Encoding.UTF8,
"application/json");
var res = await client.PostAsync(url, content);
}
Please make sure your function is async and that you await the client.PostAsync fucntion.
If someone is wondering how I finally pulled it off (with other's help) here it is :
var url = "https://gatewayt.whatever.com/chkt/request/request.php";
HttpClient client = new HttpClient();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var content = new StringContent(jsonObject, System.Text.Encoding.UTF8, "application/json");
var res = await client.PostAsync(url, content);
var jsonRes = await res.Content.ReadAsStringAsync();
This line is important var jsonRes = await res.Content.ReadAsStringAsync(); the object jsonRes will be a string value, which is actually the response. The var res will only be the status of the response, not the actual response.

The PostAsync in HttpClient doesn't send data to my webapi

I've created a HttpClient instance to invoke an API with post method.
using (var client = new HttpClient())
{
var person = new Stu();
person.ApplicantId = "48751889-D86E-487B-9508-000EAB65F11F";
var json = JsonConvert.SerializeObject(person);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var url = "http://localhost:52085/api/CollegeService/IsCoolegeStudent";
// var client = new HttpClient();
var response = await client.PostAsync(url, data);
string result = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(result);
}
public class Stu
{
public string ApplicantId { get; set; }
}
When I check my API out , I receive ApplicantId of my object is Null.
I cant not figure out why ApplicantId is Null.
Finally I've changed my [FromForm] to[FromBody] in my API and it worked correctly but it stuck on this line var response = await client.PostAsync(url, data);and doesn't go on.
the await keyboard make my app stuck ,I've changed it this way
var response = await client.PostAsync(url, data).ConfigureAwait(false);
but I didn't figure it out why it cause this problem.
If you using FromForm attribute, you should use FormUrlEncodedContent instead of StringContent as content type when you send POST message. If you still want send json - change FromForm at IsCoolegeStudent method to FromBody.

Finding result of POST in Http Response Message

I am building REST Client (c#) using windows form application in VS2017. I have been able to successfully GET and POST requests from the server using the HttpClient.PostAsJsonAsync() and ReadAsync() methods. I am trying to POST some data to the server and upon a successful POST, the server responds with a unique string like "1c77ad2e-54e0-4187-aa9d-9a55286b1f7a"
I get a successful response code (200 - OK) for the POST. However, I am not sure where to check for the resulting string. I have checked the contents of HttpResponseMessage.Content
static async Task<HttpStatusCode> PostBurstData(string path, BurstRequest
burstRequest)
{
HttpResponseMessage response = await client.PostAsJsonAsync(path, burstRequest);
response.EnsureSuccessStatusCode();
Console.WriteLine(response.Content.ToString());
// return response
return response.StatusCode;
}
The data sent to this function call is as follows:
BurstRequest request = new BurstRequest();
request.NodeSerialNumbers = SubSerialList;
request.StartTime = ((DateTimeOffset)dateTimePicker1.Value).ToUnixTimeMilliseconds();
HttpStatusCode statusCode = new HttpStatusCode();
statusCode = await PostBurstData(post_burst_url, request);
Where should I search for the string the server responds for a successful POST? Should the content be read using ReadAsync()?
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsAsync();
}
Why not trying to use HttpContent like below:
using (HttpResponseMessage response = await client.GetAsync(url)) // here you can use your own implementation i.e PostAsJsonAsync
{
using (HttpContent content = response.Content)
{
string responseFromServer = await content.ReadAsStringAsync();
}
}

How to get and print response from Httpclient.SendAsync call

I'm trying to get a response from a HTTP request but i seem to be unable to. I have tried the following:
public Form1() {
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("someUrl");
string content = "someJsonString";
HttpRequestMessage sendRequest = new HttpRequestMessage(HttpMethod.Post, client.BaseAddress);
sendRequest.Content = new StringContent(content,
Encoding.UTF8,
"application/json");
Send message with:
...
client.SendAsync(sendRequest).ContinueWith(responseTask =>
{
Console.WriteLine("Response: {0}", responseTask.Result);
});
} // end public Form1()
With this code, i get back the status code and some header info, but i do not get back the response itself. I have tried also:
HttpResponseMessage response = await client.SendAsync(sendRequest);
but I'm then told to create a async method like the following to make it work
private async Task<string> send(HttpClient client, HttpRequestMessage msg)
{
HttpResponseMessage response = await client.SendAsync(msg);
string rep = await response.Content.ReadAsStringAsync();
}
Is this the preferred way to send a 'HttpRequest', obtain and print the response? I'm unsure what method is the right one.
here is a way to use HttpClient, and this should read the response of the request, in case the request return status 200, (the request is not BadRequest or NotAuthorized)
string url = 'your url here';
// usually you create on HttpClient per Application (it is the best practice)
HttpClient client = new HttpClient();
using (HttpResponseMessage response = client.GetAsync(url).GetAwaiter().GetResult())
{
using (HttpContent content = response.Content)
{
var json = content.ReadAsStringAsync().GetAwaiter().GetResult();
}
}
and for full details and to see how to use async/await with HttpClient you could read the details of this answer

How can I get JSON data from Google API and store it in a variable?

I am trying to send an Http Get message to the Google location Api which is supposed to have Json data such as this
https://maps.googleapis.com/maps/api/geocode/json?address=Los%20Angeles,CA=AIzaSyDABt
as you noticed the response is in Json. I want to give a a Http Call to that URL and save the Json content in a variable or string. My code does not give out any errors but it is also not returning anything
public async System.Threading.Tasks.Task<ActionResult> GetRequest()
{
var client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("https://maps.googleapis.com/maps/api/geocode/json?address=Los%20Angeles,CA=AIzaSyDABt");
string data = response.Content.ToString();
return data;
}
I want to send out a Get Request using HttpClient() or anything that will send out the URL request and then save that content into a string variable . Any suggestions would be appreciated, again my code gives no errors but it is not returning anything.
Use ReadAsStringAsync to get the json response...
static void Main(string[] args)
{
HttpClient client = new HttpClient();
Task.Run(async () =>
{
HttpResponseMessage response = await client.GetAsync("https://maps.googleapis.com/maps/api/geocode/json?address=Los%20Angeles,CA=AIzaSyDABt");
string responseString = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseString);
});
Console.ReadLine();
}
If you use response.Content.ToString() it is actually converting the datatype of the Content to string so you will get System.Net.Http.StreamContent
Try this.
var client = new HttpClient();
HttpResponseMessage httpResponse = await client.GetAsync("https://maps.googleapis.com/maps/api/geocode/json?address=Los%20Angeles,CA=AIzaSyDABt");
string data = await httpResponse.Content.ReadAsStringAsync();
How about using the Json framework for .NET powered by Newtonsoft ?
You can try to parse your content to a string with this.
Well, your code can be simplified:
public async Task<ActionResult> GetRequest()
{
var client = new HttpClient();
return await client.GetStringAsync("https://maps.googleapis.com/maps/api/geocode/json?address=Los%20Angeles,CA=AIzaSyDABt");
}
However...
My code does not give out any errors but it is also not returning anything
This is almost certainly due to using Result or Wait further up the call stack. Blocking on asynchronous code like that causes a deadlock that I explain in full on my blog. The short version is that there is an ASP.NET request context that only permits one thread at a time; await by default will capture the current context and resume in that context; and since Wait/Result is blocking a thread in the request context, the await cannot resume executing.
Try this
public async static Task<string> Something()
{
var http = new HttpClient();
var url = "https://maps.googleapis.com/maps/api/geocode/json?address=Los%20Angeles,CA=AIzaSyDABt";
var response = await http.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
result = JsonConvert.DeserializeObject<string>(result);
return result;
}
return "";
}
var result = Task.Run(() => Something()).Result;

Categories

Resources