Returning the Web API response in JSON format - c#

I am trying sending a response from the API as a JSON. Currently we are calling other web service multiple times consuming it and send all the responses together as a JSON. The called web service returns response as a JSON. And below is what I am doing
List<Models.DTO.RootObject> i_response = new List<Models.TO.RootObject>();
public async Task<IHttpActionResult> Get()
{
.....
foreach (int req_id in reqIdLst)
{
using (var client_request = new HttpClient())
{
string request_Uri = BaseURL_iLab;
Uri uri_request = new Uri(request_Uri);
client_request.BaseAddress = uri_request;
client_request.DefaultRequestHeaders.Accept.Clear();
client_request.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client_request.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var request_response = await client_request.GetAsync(uri_request);
var responsefile = await request_response.Content.ReadAsStringAsync();
var request_returnDataObj = JsonConvert.DeserializeObject<Models.DTO.RootObject>(responsefile);
i_response.Add(request_returnDataObj);
}}
return Ok(i_response);
}}
But my above code throws error when debugging as
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content
type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
I am not sure how to send as a JSON instead of a XML.

Something we did where I work was to create a custom class that extends ExceptionFilterAttribute. Call it something like WebApiExceptionFilterAttribute. Create an override for OnException and set the context.Response appropriately based on the exception. You can also set the HttpStatusCode if the exception indicates a specific result, such as NotFound, Forbidden, or BadRequest, instead of just InternalServerError.
Then, in Global.asax, in Application_Start(), add GlobalConfiguration.Configuration.Filters.Add(new WebApiExceptionFilterAttribute());
Finally, when defining an ApiController, add a [WebApiExceptionFilterAttribute] annotation to the class definition.

Related

RestSharp is throwing a bad request on a GET call, but is missing response body

I am making a GET call to an external REST API. I was putting in a parameter incorrectly and was getting an HttpRequestException. When catching the exception the only details it returns are:
Request failed with status code BadRequest
When monitoring the traffic using Fiddler I can see the server was returning a json message in the body explaining why the call failed.
Is there anyway to access this message from RestSharp?
I am using .net 6 and RestSharp version 108.0.2
you must set ThrowOnAnyError from RestClientOptions to false :
private async Task<T?> SendRequest<T>()
{
string url = "your request url";
var options = new RestClientOptions(url)
{
ThrowOnAnyError = false,
MaxTimeout = 6000
};
var client = new RestClient(options);
var request = new RestRequest().AddHeader("Content-Type", "application/json");
request.Method = Method.Post;
var response = await client.ExecuteAsync<T>(request);
return response.Data;
}

Deserialize a JsonResult from C#

I access a REST API with this code :
public async Task<IActionResult> NetExplorerAPI(string AdresseAPI, object Requete, RestSharp.Method Methode)
{
var client = new RestClient(AdresseAPI);
var request = new RestRequest();
request.Method = RestSharp.Method.Post;
request.AddJsonBody(Requete);
request.AddHeader("Accept", "application/json");
//request.AddHeader("Authorization", "Bearer a844024a4e744182aeaa62dd6347b9049f9ba35650339d2b9362e1bf03a92ac0");
//IRestResponse response = await client.ExecuteAsync(request);
RestResponse response = await client.ExecuteAsync(request);
JsonResult jr = new JsonResult(response);
return (jr);
}
I want to deserialize the JsonResult to get the token in a string :
{ "token": "med6RRIikrZ-2tua9jUa6pVZubnPvhqSH6wHvtkH42TNfJGXOaI-GioUKPvfbhP7XiGG6UgjCzUnJt87kwsljQBAKEb" }
But When I serialize the JsonResult I get a lot of items I don't need to :
string s = JsonConvert.SerializeObject(jr);
{"ContentType":null,"SerializerSettings":null,"StatusCode":null,"Value":{"ContentType":null,"SerializerSettings":null,"StatusCode":null,"Value":{"Request":{"AlwaysMultipartFormData":false,"MultipartFormQuoteParameters":false,"FormBoundary":null,"Parameters":[{"DataFormat":0,"ContentEncoding":null,"Name":"","Value":{"user":"sylvain.krier#protonmail.com","password":"S#r#line2004"},"Type":3,"Encode":false,"ContentType":"application/json"},{"Name":"Accept","Value":"application/json","Type":2,"Encode":false,"ContentType":null}],"Files":[],"Method":1,"Timeout":0,"Resource":"","RequestFormat":0,"RootElement":null,"OnBeforeDeserialization":null,"OnBeforeRequest":null,"OnAfterRequest":null,"Attempts":1,"CompletionOption":0,"ResponseWriter":null,"AdvancedResponseWriter":null},"ContentType":"application/json","ContentLength":103,"ContentEncoding":[],**"Content":"{\"token\":\"wlK4LIRpOxqKOwJ2Hs554l5-WI--IrqHW7TECZ3YtdS-RpzDuQGaQeLI0qjo8NzaSPhCUYaarBcXstrI5sPlXkwCmk9\"}"**,"StatusCode":200,"IsSuccessful":true,"StatusDescription":"Ok","RawBytes":"eyJ0b2tlbiI6IndsSzRMSVJwT3hxS093SjJIczU1NGw1LVdJLS1JcnFIVzdURUNaM1l0ZFMtUnB6RHVRR2FRZUxJMHFqbzhOemFTUGhDVVlhYXJCY1hzdHJJNXNQbFhrd0NtazkifQ==","ResponseUri":"https://patrimoine-click.netexplorer.pro/api/auth","Server":"Apache","Cookies":[],"Headers":[{"Name":"Date","Value":"Tue, 19 Jul 2022 06:40:36 GMT","Type":2,"Encode":false,"ContentType":null},{"Name":"Server","Value":"Apache","Type":2,"Encode":false,"ContentType":null},{"Name":"Pragma","Value":"no-cache","Type":2,"Encode":false,"ContentType":null},{"Name":"Cache-Control","Value":"no-store, must-revalidate, no-cache","Type":2,"Encode":false,"ContentType":null},{"Name":"X-NetExplorer-Version","Value":"7.4.4.12","Type":2,"Encode":false,"ContentType":null},{"Name":"Access-Control-Allow-Origin","Value":"*","Type":2,"Encode":false,"ContentType":null},{"Name":"X-UA-Compatible","Value":"IE=edge,chrome=1","Type":2,"Encode":false,"ContentType":null},{"Name":"Connection","Value":"close","Type":2,"Encode":false,"ContentType":null},{"Name":"X-Content-Type-Options","Value":"nosniff","Type":2,"Encode":false,"ContentType":null},{"Name":"Transfer-Encoding","Value":"chunked","Type":2,"Encode":false,"ContentType":null}],"ContentHeaders":[{"Name":"Expires","Value":"Thu, 19 Nov 1981 08:52:00 GMT","Type":2,"Encode":false,"ContentType":null},{"Name":"Content-Type","Value":"application/json","Type":2,"Encode":false,"ContentType":null},{"Name":"Content-Length","Value":"103","Type":2,"Encode":false,"ContentType":null}],"ResponseStatus":1,"ErrorMessage":null,"ErrorException":null,"Version":"1.1","RootElement":null}}}
I don't know how to get the "content" item.
From RestSharp's official QuickStart:
When using typed ExecuteAsync<T>, you get an instance of RestResponse<T> back, which is identical to RestResponse but also contains the T Data property with the deserialized response.
None of ExecuteAsync overloads throw if the remote server returns an error. You can inspect the response and find the status code, error message, and, potentially, an exception.
Extensions like GetAsync<T> will not return the whole RestResponse<T> but just a deserialized response. These extensions will throw an exception if the remote server returns an error. The exception will tell you what status code was returned by the server.
It looks like you have to choices:
Use client.ExecuteAsync and then response.Data
Use client.GetAsync<T>
For client.GetAsync you'll need a new type. For exmaple
public class MyTokenClass { public string token {get; set;} }
and then var t = await client.GetAsync<MyTokenClass>().
I think this is what you looking for let me know if you need something specific.
string theToken = JObject.Parse(response.Content)["token"].ToString();
When you get a Response object from ExecuteAsync, response is already deserialized into c# Response class, but Content is not. In this case Content contains a json string. You can parse the string to get a token (or deserialize it if you create a custom class)
This code will return { "token": "med6RRIikrZ-2tua9jUa6p...} as an ActionResult
string token = (string)JObject.Parse(response.Content)["token"];
return Ok( new { token = token});
You need to return JsonResult with the Content property of RestResponse:
return new JsonResult(response.Content);

How to return JSON response object

I am getting this error even though I added media formatter as follows. I am testing with postman. Postman headers content-type is application/json and body is x-www-form-urlencoded. How can I fix it?
"ExceptionMessage": "No MediaTypeFormatter is available to read an
object of type 'Initiate' from content with media type 'text/html'.",
"ExceptionType": "System.Net.Http.UnsupportedMediaTypeException"
Here is my code sample:
[RoutePrefix("api/v1/pin")]
public class GameController : ApiController
{
// POST: api/Game
[HttpPost, Route("initiation")]
public async System.Threading.Tasks.Task<Initiate> PurchaseInitiationAsync([FromBody]Initiate value)
{
if (value == null)
{
var message = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent(string.Format("Request is NULL! Please check your data.")),
ReasonPhrase = "Request is NULL! Please check your data."
};
throw new HttpResponseException(message);
}
HttpClient httpClient = new HttpClient();
HttpContent content = new StringContent(
JsonConvert.SerializeObject(value),
Encoding.UTF8,
"application/json"
);
HttpResponseMessage response =
await httpClient.PostAsync("http://test:1907/purchase_initiation", content);
var obj = response.Content.ReadAsAsync<Initiate>(
new List<MediaTypeFormatter>
{
new JsonMediaTypeFormatter()
}).Result;
return obj;
}
}
I can only reproduce this if the request content type hitting api/v1/pin/initiation is text/html. You say that your Postman settings are set to application/json and body is x-www-form-urlencoded, but from my testing if that was the case the exception you've shown above wouldn't be thrown.
I would double check that Postman is actually sending the correct content type header by opening the Postman console (CTRL+ALT+C) and inspecting the request headers.

Adding Comment to Fortify Issue via REST API results in Content Encoding Error

I'm trying to add a comment to an issue inside Fortify. When I POST what I think is the correct JSON, I receive the response "{"message":"Content was incorrectly formatted (expected application/json; charset=utf-8).","responseCode":400,"errorCode":-20209}"
However, if I use Fiddler to examine the message I'm POSTing and receiving the appropriate headers appear to be in place. What secondary issue could be causing this exception to be thrown?
Fortify v18.10.0187
.NET v4.6.2
Newtonsoft.Json v9.0.0
public static string PostCommentIssue(FortifyComment fc)
{
var content = JsonConvert.SerializeObject(fc);
var postUri = String.Format(Configuration.FortifyCommentsUri, fc.data.issueId);
return WebServiceHelper.PostMessage(postUri, content);
}
public static string PostMessage(string url, string content)
{
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, url);
requestMessage.Headers.Add("Authorization", Configuration.FortifyAuthorization.ToHeader());
requestMessage.Content = new StringContent(content, Encoding.UTF8, JsonMediaTypeFormatter.DefaultMediaType.MediaType);
HttpResponseMessage hrm = HttpClient.SendAsync(requestMessage).Result;
hrm.EnsureSuccessStatusCode();
HttpContent hc = hrm.Content;
return hc.ReadAsStringAsync().Result;
}
FortifyComment is just an object with the basic elements of a comment in it. It's based on the Fortify response given on a query (thus the inner data element).
Using
FortifyComment fc = new FortifyComment();
fc.data.issueId = defect.id;
fc.data.comment = String.Format("TFS #{0}.", tfsNumber);
FortifyHelper.PostCommentIssue(fc);
I receive the 400 error. Screenshot of Fiddler intercept:

Invalid operation during the http request

I'm writing a windows forms app where user have to enter email address and I need to check if it's valid.
I have found Mashape API but I get an exception;
"An unhandled exception of type 'System.InvalidOperationException' occurred in System.Net.Http.dll" error in Unirest library.
Error occurs in line with msg.Headers.Add(header.Key, header.Value);
Values are:
header.Key = "Content-type"
header.Value = "application/json"
Debugger says:
"Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."
I can't find any solution, does anyone has any idea how to fix it?
Task<HttpResponse<EWSemail>> response = Unirest.post("https://email.p.mashape.com/")
.header("X-Mashape-Key", myKey)
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.body("{\"email\":\"" + tbEmail.Text + "\"}")
.asJsonAsync<EWSemail>();
Unirest library:
private static Task<HttpResponseMessage> RequestHelper(HttpRequest request)
{
if (!request.Headers.ContainsKey("user-agent"))
{
request.Headers.Add("user-agent", USER_AGENT);
}
var client = new HttpClient();
var msg = new HttpRequestMessage(request.HttpMethod, request.URL);
foreach (var header in request.Headers)
{
msg.Headers.Add(header.Key, header.Value);
} // ^^"Content-Type" ^^ "application/json"
if (request.Body.Any())
{
msg.Content = request.Body;
}
return client.SendAsync(msg);
}
The error message says:
"Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."
Content-Type, as the name would imply, is a content header. Therefore, set it on msg.Content.Headers, not msg.Headers.
If I remember correctly, you can set it directly via msg.Content.Headers.ContentType = new MediaHeaderTypeValue("application/json");
OK, it doesn't work because syntax that Mashape provide is bad. In this case header.Key has to be "ContentType" (Reference: https://msdn.microsoft.com/en-us/library/system.net.httprequestheader%28v=vs.110%29.aspx).
I'm sorry for my rubbish post and thank you #codran, your answer helped me to find this answer.

Categories

Resources