I have problem understanding sending Json from WebApi to Android. I know how to make requests from Json, but don't know how to make Task that waits for request and return Json. I have json made from Mongo DB query with JsonConvert.SerializeObject.
I have been searching and found this that I have for now, but this isn't what I need I think, I don't have url in PostAsync, I just want to wait for request and respond with Json, where I need to look for:
public async Task<HttpStatusCode> SendAsync()
{
var content = new StringContent(
jsonString,
Encoding.UTF8,
"application/x-www-form-urlencoded");
HttpResponseMessage response = await _httpClient.PostAsync(_url, content);
return response.StatusCode;
}
You need to return an IHttpActionResult implementation. For example:
public async Task<IHttpActionResult> SendAsync()
{
// Object passed to Ok will be automatically serialized to JSON
// if response content type is JSON (and, by default, this is the serialization
// format in ASP.NET WebAPI)
return Ok(new { text = "hello world" });
}
Related
I have a code like:
[HttpPost("ConsumeApiKavling")]
public async Task<HttpStatusCode> ConsumeApiKavling([FromBody] Kavlings model)
{
string apiBaseUrl = configuration.GetValue<string>("WebAPIBaseUrl");
HttpClient client = new HttpClient();
StringContent content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
var Response = await client.PostAsync(apiBaseUrl, content);
return Response.StatusCode;
}
So when I run, the apiBaseUrl will send a response something like:
{
KavlingID: '4x',
Status: 'OK'
}
From that response, how can I get it? I mean, I want to save it to my table in the database.
Please advise.
Thank you.
Depending on the approach you want to take, you could use the following workflow:
Create the Model that will hold the API response
(Optional): Create a Data Transfer Object (DTO) or ViewModel with the properties that you are going to pass to your data access service/database
Read the body content from the API response with:
string jsonResult = await response.Content.ReadAsStringAsync();
Deserialize the returned JSON object (read JSON into your .NET object)
var responseModel = JsonSerializer.Deserialize<ResponseModel>(jsonResult);
(Optional): Map your Model to your DTO and pass it over to the data access service
NOTE: You could use the JsonSerializerOptions if you want some extra options for your JSON deserialization
I'm using HttpClient in .Net core 3.1. Most of my requests follow a similar pattern regardless of the HTTP method used:
build URL
build (optional) JSON payload
send request
await response
check status code
parse (optional) JSON response
so I've built a wrapper function that does all these things, and it takes the HTTP method as a parameter. However, when it comes to the "send request" step, I need to use a switch statement to invoke the appropriate method on HttpClient to invoke.
I'm sure that under the skin, get GetAsync() PostAsync() etc. are calling the same underlying function and passing the Http method as a parameter. but I can't see any way of calling it like this from the outside. It seems a strange omission as in my experience most HTTP libraries work that way.
Hope this will help you.
// For JsonConvert use Newtonsoft.Json
string url = "YourURL";
string body = JsonConvert.SerializeObject(BodyModel);
string headerParameter = "ASD123456789";
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // Content-Type of request, it can be application/xml to other
client.DefaultRequestHeaders.Add("Device", headerParameter ); // first is name, second one is value
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url) // there you can have Get, Post, Put, Delete and etc. And every request needs to be configured by its settings
{
Content = new StringContent(body, Encoding.UTF8, "application/json")
};
HttpResponseMessage response = await client.SendAsync(request);
if ((int)response.StatusCode == 200)
{
string responseString = await response.Content.ReadAsStringAsync();
ResponseModel responseModel = JsonConvert.DeserializeObject<ResponseModel>(responseString);
}
Someone's probably done this before but I can't seem to formulate the question properly to find results. I want to make AJAX calls from a view, but I can't directly call the external API from javascript because there's a key that I can't expose. My idea is to have another controller action that I call from the page that calls the actual external REST API I want to get data from and just passes it on as a JSON. I see lots of examples of getting a JSON through C# and deserializing it but not many where you get a JSON and then return it and consume it from the view. Any help appreciated.
public JsonResult GetStuff()
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("Stuff/?Id=" + id).Result;
*code to take response and pass it on as a JSON that I can consume from Javascript
}
Here is what I recommend.
[HttpGet("myapi/{id}");
public async Task MyApi(int id) {
// Replace these lines as needed to make your API call properly.
using HttpClient client = new() {
BaseAddress = REMOTE_SERVER_BASE
}
// Make sure to properly encode url parameters if needed
using HttpResponseMessage response = await client.GetAsync($"myapi/{id}");
this.HttpContext.Response.StatusCode = (int)response.StatusCode;
foreach (KeyValuePair<string, IEnumerable<string>> header in response.Headers) {
this.HttpContext.Response.Headers[header.Key] = new StringValues(header.Value.ToArray());
}
await response.Content.CopyToAsync(this.HttpContext.Response.Body);
}
This will copy all the common response fields such as status code, headers, and body content, over to your response.
This code isn't tested so you might have to tweak it a bit but it should be enough to get you started.
I am making a POST request to a route which is returning JSON data.
[HttpPost("api/v1/testGetAll")]
public object Test([FromBody]object filteringOptions)
{
return myService.GetLogs(filteringOptions).ToArray();
}
Route works fine, filtering works fine, and when I test the route in Postman I get the right response. However this is only a back-end, and I would like to invoke this route from my custom API gateway.
The issue I'm facing is getting that exact response back. Instead I am getting success status, headers, version, request message etc.
public object TestGetAll(string ApiRoute, T json)
{
Task<HttpResponseMessage> response;
var url = ApiHome + ApiRoute;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
try
{
response = client.PostAsync(url, new StringContent(json.ToString(), Encoding.UTF8, "application/json"));
return response.Result;
}
catch (Exception e)
{
...
}
}
}
How can I get exact content back?
You need to read the content from response.
var contentString = response.Result.Content.ReadAsStringAsync().Result;
If you wish, you can then deserialize the string response into the object you want returning.
public async Task<TResult> TestGetAll<TResult>(string apiRoute, string json)
{
// For simplicity I've left out the using, but assume it in your code.
var response = await client.PostAsJsonAsync(url, json);
var resultString = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<TResult>(resultString);
return result;
}
You have to return the response as an HttpResponseMessage.
Try changing your return statement to
[HttpPost("api/v1/testGetAll")]
public IHttpActionResult Test([FromBody]object filteringOptions)
{
return Ok(myService.GetLogs(filteringOptions).ToArray());
}
Please note: This will return the response with status code 200. In case you want to handle the response based on different response code. You can create the HttpResponseMessage like this-
Request.CreateResponse<T>(HttpStatusCode.OK, someObject); //success, code- 200
Request.CreateResponse<T>(HttpStatusCode.NotFound, someObject); //error, code- 404
T is your object type.
And so on...
So I have built an REST API that in itself also consumes another API. Now I could just call the other api, create objects from that call and then make a new request and send it on it's way but that would use up a bit of performance.
I tried just sending the second request again but the problem is that Content serializes it again so I get alot of backslashes. This is my code that does this:
[Route("")]
public IHttpActionResult GetAllDevices()
{
var request = new RestRequest();
request = new RestRequest("devices", Method.GET);
IRestResponse response = client.Execute(request);
return Content(HttpStatusCode.OK, response.Content);//response.Content get's serialized again.
}
As I said, I could deserialized the first call and then just put that in Content, but it feels unnecessary.
Here is one way of doing it, remember to set the content-type explicitly to application/json if needed:
[HttpGet]
[Route("test")]
public HttpResponseMessage Test()
{
const string json = "{ \"test\": 123 }"; // from RestClient
var res = Request.CreateResponse();
res.Content = new StringContent(json);
res.Content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
return res;
}