I am calling an API Post method, however, I am not sure what I am doing wrong but the value in the API is always null. The method I am calling the API from is below. When I hit this I can see Ids is list of ints with 5 values for example.
private void Save(List<int> Ids)
{
var myAPI = ConfigurationManager.AppSettings["MyAPI"];
string myIds = string.Join(",", Ids);
using (var client = new HttpClient())
{
int result = client.PostAsync(myAPI, new { test = myIds }, new JsonMediaTypeFormatter())
.Result
.Content
.ReadAsAsync<int>()
.Result;
}
}
My API signature is like below - with a breakpoint on I can see it is getting hit but test the parameter I am trying to pass is always null
[HttpPost]
[Route("api/MyController/SaveData")]
public HttpResponseMessage SaveData([FromBody]List<string> test)
{
try
{
//Rest of method removed for brevity
I have tried removing the [FromBody] Annotation from the WebAPI controller but test still is getting null with breakpoint in the SaveData API method
Try this:
private void Save(List<int> Ids)
{
var myAPI = ConfigurationManager.AppSettings["MyAPI"];
using (var client = new HttpClient())
{
var requestBody = JsonConvert.SerializeObject(Ids);
var postRequest = new StringContent(requestBody, Encoding.UTF8, "application/json");
var response = client.PostAsync(myAPI, postRequest).GetAwaiter().GetResult();
var rawResponse = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
// Do something with the answer
}
}
I also suggest to make the method private Task Save and replace .GetAwaiter().GetResult(); with await in front of that calls.
In my case i used System.Web.Http.ApiController instead of System.Web.Mvc.Controller. So over all code looks like
public class YourAppController : ApiController
{
[System.Web.Http.Route("publish-message")]
public HttpResponseMessage Post([System.Web.Http.FromBody] string msges)
{
//Your Code
return Request.CreateResponse(HttpStatusCode.OK, "");
}
}
public async Task<string> PublishMessageCall(string publishMessage){
var returnval = "";
string httpWebRqst = "http://localhost:543134535/publish-message";
using (HttpClient myClient = new HttpClient())
{
var jsonString = JsonConvert.SerializeObject(publishMessage);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var response = await myClient.PostAsync(httpWebRqst, content);
var responseString = await response.Content.ReadAsStringAsync();
}
return await Task.FromResult(returnval);}
Related
So I've looked around for an answer for this but nothing I've found even comes close to solving it.
I'm trying to set up a Post method on my Web API but no matter what I do it just gives me an internal server error.
I've tried adding [FromBody] (it's a simple type).
HttpClient client {get;set;}
public APICall()
{
client = new HttpClient
{
BaseAddress = new Uri("http://localhost:1472/api/")
};
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-protobuf"));
}
public void PostTimeTaken(long timeTaken)
{
var response = client.PostAsJsonAsync("Logging", timeTaken).Result;
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.ReasonPhrase);
}
}
and then my controller action looks like this:
public void Post([FromBody] long timeTaken)
{
_api.DataBuilder.NumberOfAPICalls += 1;
_api.DataBuilder.ResponseTimes.Add(timeTaken);
}
I get no error message that could actually explain what's going on, just "Internal server error"
------SOLVED-------
Just in case anyone stumbles across this looking for the same answer, the issue was I was sending the data to the server in an incorrect format, it needed to be ProtoBuf serialised first, code snippet for anyone it might help:
public void PostToAPI(int ThingToSend)
{
using (var stream = new MemoryStream())
{
// serialize to stream
Serializer.Serialize(stream, ThingToSend);
stream.Seek(0, SeekOrigin.Begin);
// send data via HTTP
StreamContent streamContent = new StreamContent(stream);
streamContent.Headers.Add("Content-Type", "application/x-protobuf");
var response = client.PostAsync("Logging", streamContent);
Console.WriteLine(response.Result.IsSuccessStatusCode);
}
}
using (var client = new HttpClient())
{
string url = "http://localhost:7936";
client.BaseAddress = new Uri(url);
var jsonString = JsonConvert.SerializeObject(contentValue);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await client.PostAsync("/Api/Logger/PostActionLog", content);
string resultContent = await result.Content.ReadAsStringAsync();
}
Have you tried to convert
long timeTaken to A model like;
public class TimeModel {
public long TimeTaken {get;set;}
}
public void Post([FromBody] TimeModel time){
// Do Stuff
}
Here the code of creating a simple server
baseUrl = "http://localhost:1472/"; // change based on your domain setting
using (WebApp.Start<StartUp>(url: baseUrl))
{
HttpClient client = new HttpClient();
var resp = client.GetAsync(baseUrl).Result;
}
Here some changes in your code
var requestData = new List<KeyValuePair<string, string>> // here
{
new KeyValuePair<string, string>( "Logging",timeTaken),
};
Console.WriteLine("request data : " + requestData);
FormUrlEncodedContent requestBody = newFormUrlEncodedContent(requestData);
var request = await client.PostAsync("here pass another server API", requestBody);
var response = await request.Content.ReadAsStringAsync();
Console.WriteLine("link response : " + response);
Pls add your controller
[HttpPost] // OWIN - Open Web Interface for .NET
public HttpResponseMessage Post([FromBody] long timeTaken)
{
_api.DataBuilder.NumberOfAPICalls += 1;
_api.DataBuilder.ResponseTimes.Add(timeTaken);
return Request.CreateResponse(HttpStatusCode.OK); //Using Post Method
}
I have an endpoint in my ASP.NET Core 2.1 Controller
[HttpPost]
public async Task<bool> CheckStatus([FromBody] StatusModel model)
{
...code ommited
return true;
}
And I call this endpoint from other place in code like this:
await client.PostAsync('/CheckStatus', payloayd)
How can I retrive a bool value from this request?
Using Newtonsoft.Json, you can read the response of the request and parse it into a bool.
using Newtonsoft.Json;
public async Task<bool> GetBooleanAsync()
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = new { };
var url = "my site url";
var payload = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
var req = await client.PostAsync(url, payload);
var response = await req.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<bool>(response);
}
}
UPDATE
Looking back on this from a few years on, this can be simplified without the use of Newtonsoft.Json to read the response, by simply parsing the string data to a boolean.
public async Task<bool> GetBooleanAsync()
{
var data = new { };
var url = "my site url";
var payload = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
using var client = new HttpClient();
var response = await client.PostAsync(url, payload);
var data = await response.Content.ReadAsStringAsync();
return boolean.Parse(data);
}
However, if your boolean value is returned in a JSON object, then Newtonsoft.Json could be used to read that value.
i have the following API json request
"myjsonrequest": {
"ServiceKey": "Hello",
"Identityvals": {
"IDName": "regnum",
"IDValue": "112233"
}
}
any simple way to get the response , im using ASP.net c#
i tried this code
HttpClient client = new HttpClient();
string x = "{'IDName','regnum'},{'IDValue','112233'}";
var Keys = new Dictionary<string, string>
{
{ "ServiceKey", "hello" },
{ "PractitionerIdentity",x}
};
var content = new FormUrlEncodedContent(Keys);
var response = await client.PostAsync("https://apiurl", content);
var responseval = await response.Content.ReadAsStringAsync();
Try this :
var json = new {
ServiceKey = "",
PractitionerIdentity = new {
IDName = "" ,
IDValue = ""
}
};
HttpClient client = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json")
var response = await client.PostAsync("https://apiurl", content);
Your Json data should be saved to a model in the following way:
public class YourJsonData{
public string ServiceKey {get; set;}
//add other names
}
The best thing about this is that if you call your object, you get a variable back for easy usage.
then you can add it in a task:
public async Task<List<YourJsonData>> GetJsonAsync(CancellationToken cancellationToken = default)
{
using (var client = new HttpClient())
{
//Make the request, and ensure we can reach it
var response = await client.GetAsync(yourJosnUrl, cancellationToken);
if (response.IsSuccessStatusCode)
{
//Read the actual stream (download the content)
var content = await response.Content.ReadAsStringAsync();
//Make sure we do have some valid content before we try to deserialize it
if (string.IsNullOrEmpty(content))
{
return new List<YourJsonData>();
}
//Deserialize into a list of yourjsondata
return JsonConvert.DeserializeObject<List<YourJsonData>>(content);
}
}
return new List<YourJsonData>();
}
also if you are lazy, you can replace YourJsonData with dynamic. the downpart here is that you won't be able to see what you are revering to.
How do I PostAsync() with multiple simple types as parameters, I have the action controller below:
[HttpPost]
[Route("users/verifyLoginCredentials/{username}/{password}")]
public IHttpActionResult VerifyLoginCredentials([FromUri]string username, string password)
{
//Do Stuff......
return Ok("Login Successful");
}
I am trying to invoke it from a .Net Framerwork 4.5 Client application as below:
static async Task<Uri> CreateProductAsync(string username, string password)
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(uri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var value = new Dictionary<string, string>
{
{ "username", "test123" }
};
var content = new FormUrlEncodedContent(value);
var result = await client.PostAsync("users/verifyLoginCredentials/{username}/{password}", content);
string resultContent = await result.Content.ReadAsStringAsync();
result.EnsureSuccessStatusCode();
// return URI of the created resource.
return result.Headers.Location;
}
I have tried mutiple ways so far and have done a lot of reading, most recently here.
I understand that it is easier to deal with complex types than it is to deal with simple types and that by default complex types are encoded into the request body/content while simple types are encoded into the URI.
I have tried to post data by sending key/value pairs encoded using FormUrlEncodedContent(string) by sending Json through StringContent(), I have tried with both single and multiple parameters but I understand the limitation is only with complex types now.
I have read many MSDN posts and tutorials, maybe I am missing a crucial piece of information.
The controller action above does get executed but with both paramerters having a
string value of "{username}" and "{password}"
When you write
[Route("users/verifyLoginCredentials/{username}/{password}")]
You are saying "match the username and password parameters, in the specified order, from the Uri", so whatever you send through the body of the POST will be ignored.
You are explicitly passing {username} and {password} as parameters:
var result = await client.PostAsync("users/verifyLoginCredentials/{username}/{password}", content);
You should be doing this instead:
var message = new HttpRequestMessage(HttpMethod.Post, "users/verifyLoginCredentials/username/test123");
var result = await client.SendAsync(message);
string resultContent = await result.Content.ReadAsStringAsync();
If you want to post the data as the body instead of part of the URL, use this:
[Route("users/VerifyLoginCredentials")]
public IHttpActionResult VerifyLoginCredentials(string username, string password)
var value = new Dictionary<string, string>
{
{ "username", "yourUsername" },
{ "passwird", "test123" }
};
var content = new FormUrlEncodedContent(value);
var result = await client.PostAsync("users/verifyLoginCredentials/", content);
string resultContent = await result.Content.ReadAsStringAsync();
The simplest way would be to create a model which contains everything you need.
An example would be:
public class LoginModel
{
[Required]
public string Username { get;set }
[Required]
public string Password { get;set }
}
you can now do:
[HttpPost]
[Route("users/verifyLoginCredentials")]
public IHttpActionResult VerifyLoginCredentials([FromBody]LoginModel model)
{
//validate your model
if ( model == null || !ModelState.IsValid )
{
return BadRequest();
}
//stuff
return Ok();
}
To use it you would do something like this:
var model = new LoginModel { Username = "abc", Password="abc" } ;
using (var client = new HttpClient())
{
var content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
var result = await client.PostAsync("your url", content);
return await result.Content.ReadAsStringAsync();
}
Do not send passwords in the URI as anyone can intercept the request and see what the password is.
Any data which needs to remain secret you send it in the body of the request and make sure the request is over https as that encodes the headers and the post body so no one can look at the data.
[HttpPost("{coverPagePath}")]
public void Post([FromRoute] string coverPagePath, [FromBody] UserCoverpage value)
{
var args = new[] { WebUtility.UrlDecode(coverPagePath).Replace("\\", "/") };
userCoverpageService.Create(value, args);
}
...
//test:
var json = item.SerializeToJson(true);
HttpContent payload = new StringContent(json, Encoding.UTF8, "application/json");
// act
var response = await httpClient.PostAsync($"/api/UserCoverpage/{coverPagePath}", payload);
var data = await response.Content.ReadAsStringAsync().ConfigureAwait(true);
output.WriteLine(data);
I'm learning how to create WEB-API client
I've created some simple API:
[HttpGet]
public IHttpActionResult GetInfo()
{
return Ok("Its working!");
}
[HttpPost]
public IHttpActionResult PostInfo(ClientDataDto dto)
{
try
{
someMethod(dto.IdKlienta, dto.Haslo, dto.IdZgloszenia, dto.HardwareInfo, dto.SoftwareInfo);
return Ok("sent");
}
catch
{
return BadRequest();
}
}
For now I just trying to call GET method.
When I use Fiddler with addr
localhost:someport/api/Client2
its working
but when i try to do it by client, which code is below:
private static HttpClient client = new HttpClient();
static void Main(string[] args)
{
#region TESTONLY
var debug = new XMLData();
string HardwareInfoXML = debug.HardwareXML;
string SoftInfoXML = debug.SoftwareXML;
int id_zgloszenia = 20;
int idKlienta = 25;
//haslo = "202cb962ac59075b964b07152d234b70";
#endregion
var data = new ClientDataDto() { HardwareInfo = HardwareInfoXML, SoftwareInfo = SoftInfoXML, IdKlienta = idKlienta, IdZgloszenia = id_zgloszenia };
RunAsync(data);
}
private static async Task RunAsync(ClientDataDto data)
{
var stringContent = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.BaseAddress = new Uri(#"http://localhost:7774/api/client2/");
var url = new Uri(#"http://localhost:7774/api/client2/");
var res1 = await client.GetAsync(url);
var res = await client.PostAsync(url, stringContent);
res.EnsureSuccessStatusCode();
}
Application closing without any info at
var res1 = await client.GetAsync(url);
I have checked to see all exceptions in Debug exception Windows, but it is just closing after trying call GetAsync
PostASync doesn't work too.
What is wrong here?
i'm really sorry that i've posted simpe problem.
sulotion is to add .Wait() on RunAsync(data);
RunAsync(data).Wait();