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;
}
Related
I'm trying to pass xml file to api using RestSharp, but I'm receiving the file at the Post method as null.
Here is my code:
public void SendXmlToApi()
{
var client = new RestClient(_uri);
var request = new RestRequest(Method.POST);
request.AddFile("Xml",XmlPath);
request.RequestFormat = DataFormat.Xml;
request.AddHeader("content-type", "application/xml");
var response = client.Execute(request);
bool res = (response.StatusCode == HttpStatusCode.OK);
}
And my Post Func:
[HttpPost]
[Route("Test")]
public void UpdateResult(XDocument a)
{
}
Any idea whats the problem?
I don't use XML, so this deviates a little from your example, but it is a viable option for posting XML into a [HttpPost] API endpoint. I used your SendXmlToApi() example untouched (just supplied my own _uri and XmpPath variables) and was successful (Core 3.1).
I modified your receiving code to be:
[HttpPost]
[Route("test")]
public async Task UpdateResult()
{
string body = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
XDocument xdoc = XDocument.Parse(body);
}
Of course, you'll want to put guard rails on this and have proper error handling and validation, but it should get you over the hump.
Below is code snippet for POST api call where I am stuck with error:
Bad request
After searching the web, I understand that you get this error when you don't follow proper payload syntax or pass proper payload data while making a post api call.
Here are different ways that I tried so far but unfortunately none work.
// payload data's class represantation,
public class DNCAddressInfo
{
[JsonProperty("dncAddress")]
public string DNCAddress { get; set; }
[JsonProperty("checkForPhoneRejection")]
public bool CheckForPhoneRejection { get; set; }
[JsonProperty("checkForPhoneFormats")]
public bool CheckForPhoneFormats { get; set; }
}
First try:
DNCAddressInfo dncObj = GetPayloadData();
string payload = JsonConvert.SerializeObject(dncObj);
var content = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsJsonAsync(url, content).ConfigureAwait(false); // response: error code: 400 , bad request
Second try:
DNCAddressInfo dncObj = GetPayloadData();
JObject jsonObject = new JObject
{
["dncAddress"] = JsonConvert.SerializeObject(dncObj.DNCAddress),
["checkForPhoneRejection"] = JsonConvert.SerializeObject(dncObj.CheckForPhoneRejection),
["checkForPhoneFormats"] = JsonConvert.SerializeObject(dncObj.CheckForPhoneFormats)
};
var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsJsonAsync(url, content).ConfigureAwait(false);// response: error code: 400 , bad request
Third try:
string payload = "{\"dncAddress\": \"91#1231123\", \"checkForPhoneRejection\": false, \"checkForPhoneFormats\": false}"; // sample payload data taken from api providers document
var content = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsJsonAsync(url, content).ConfigureAwait(false); // response: error code: 400 , bad request
All three approaches resulted in same error,
StatusCode: 400, ReasonPhrase: '400'
Request header is ,
Headers = {Authorization: Basic XXXXX;
Accept: application/json
X-Requested-With: rest
Cache-Control: no-cache
}
Response from Postman looks all fine. Here is snapshot of same.
Is there anything I am doing wrong here or missing anything?
With PostJsonAsync method, you don't need to manually serialize an object to json, just pass it as it is:
DNCAddressInfo dncObj = GetPayloadData();
HttpResponseMessage response = await _client.PostAsJsonAsync(url, dncObj).ConfigureAwait(false);
or you can use newer HttpClient.PostAsync:
DNCAddressInfo dncObj = GetPayloadData();
string payload = JsonConvert.SerializeObject(dncObj);
var content = new StringContent(payload, Encoding.UTF8, "application/json");
HttpResponseMessage response = await _client.PostAsync(url, content).ConfigureAwait(false);
References: HttpClient.PostAsync Method, HttpClientExtensions.PostAsJsonAsync Method
"PostAsJsonAsync" method serializes data inside. When you pass "StringContent" to this method then HttpClient serializes "StringContent" to Json and sends wrong data.
Try to use "PostAsync" instead of "PostAsJsonAsync".
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
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...
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" });
}