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
Related
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 have a client Call my API service as this:
var paramDiction = new Dictionary<string, string>{{"datefROM", "2018/1/1"}};
string content = JsonConvert.SerializeObject(paramDiction);
var stringContent = new StringContent(content, Encoding.UTF8, "application/json");
// call the API service
var x = await _httpClient.PostAsync(url, stringContent);
I tried many ways to get the stringContent from Server Side, but still can't get it. I'm I on the wrong way?
[HttpPost]
[Route("GetStringContent")]
public IActionResult GetStringContent()
{
var stringContent = Request.HttpContext.ToString();
return stringContent;
}
Don't know why the Request here is a httpRequest, only have the HTTPContext and this httpContent can't read the content out like
Request.Content.ReadAsStringAsync();
First of all for API Methods you normally return a HttpResponseMessage that you can create with Request.CreateResponse(HttpStatusCode, Message).
Now to your question, in Asp.Net an API Method has parameters according to what you're expecting to be sent. For Example in your case your Method signatrue would look like this public HttpResponseMessage GetStringContent([FromBody] Dictionary<string, string> stringContent). The [FromBody] Attribute is used in Post Methods to signal that the Content is coming from the request body
HeyGuys
I'm working on a WebApi project that receives requests from clients and redirects these requests to other services that are not open for direct access.
By default, .Net serializes and deserializes the Json request parameters automatically, so I need to re-serialize them before calling the appropriate service. The same problem occurs when receiving the service response. I need to deserialize it before sending the response to the user; otherwise .Net framework will serialize it one more time, resulting in a "Json of Json" response.
I found this answer but it does not seem to work with .NetCore; so I tried to create my own ModelBinder that just reads the Json object and returns it.
class JsonUnformatterBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
return new JsonUnformatterBinder(new SimpleTypeModelBinder(context.Metadata.ModelType));
}
}
and
class JsonUnformatterBinder : IModelBinder
{
private readonly IModelBinder _fallbackBinder;
public JsonUnformatterBinder(IModelBinder fallbackBinder)
{
_fallbackBinder = fallbackBinder;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
string currMethod = bindingContext.ActionContext.HttpContext.Request.Method;
if ("POST".Equals(currMethod) || "PUT".Equals(currMethod))
{
string strData = new StreamReader(bindingContext.ActionContext.HttpContext.Request.Body).ReadToEnd();
bindingContext.Result = ModelBindingResult.Success(strData);
return Task.CompletedTask;
}
return _fallbackBinder.BindModelAsync(bindingContext);
}
}
This code is very simple, it was my first attempt and it worked well for my purposes. However, I still get the "Json of Json" problem when I take the second service answer and returns back to the user.
I basically have no idea what I can do to overcome this, so any workaround is welcome here.
If you need just redirect a request without modification, you could read it from input stream directly and send it to inner service. You could also use such approach to read responce from inner service.
//1. Set empty parameter list in action then neither serializator nor model binder are not invoked.
public async Task<ContentResult> ProxyAction(/*empty parameter list*/)
{
var newUrl = #"https://stackoverflow.com";
var data = this.Request.Body;
using (var client = new HttpClient())
{
//2. Read request body from input stream.
var reader = new StreamReader(data);
var json = reader.ReadToEnd();
using (var content = new StringContent(json))
{
//3. Set correct content type
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(this.Request.ContentType);
//4. Post request to inner service
var response = await client.PostAsync(newUrl, content);
//5. Read response without deserialization
var innerResponse = await response.Content.ReadAsStringAsync();
var contentType = response.Content.Headers.ContentType.ToString();
var statusCode = response.StatusCode;
//6. Return inner response without serialization
var outerResponse = this.Content(innerResponse, contentType);
outerResponse.StatusCode = (int)statusCode;
return outerResponse;
}
}
}
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;
}
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" });
}