I have this:
public Int32 NumberOfLocationsForCompany(int companyId)
{
var response = _curl.ResetRequest()
.WithPath(LOCATION_URL)
.AddParam("companyId", companyId.ToString())
.RequestAsGet()
.ProcessRequest<Int32>();
return response;
}
that calls this at the end.
public T ProcessRequest<T>() where T : new()
{
var response = _client.Execute<T>(_request);
if (response.ErrorException != null)
{
throw response.ErrorException;
}
return response.Data;
}
but I get this error. I don't get why it's trying to map an int to a collection or why it's Int64 vs the 32 I specified.: Unable to cast object of type 'System.Int64' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.
When I hit the api directly this is what I get back
<int xmlns="http://schemas.microsoft.com/2003/10/Serialization/">17</int>
I feel it's something I'm not understanding about Rest Sharp. I tell the execute method to expect an Int, it receives and int, but is trying to map it to a collection. Why and where does the collection come from?
I have noticed that when I look into the base response object's Content the appropriate result "17" is present, why can't Rest Sharp find it? and still where is it finding the Collection?
When looking at the response object I found the return value was in Content vs in Data. I found this to be true whenever I was not returning an object or list of objects.
So now when I'm expecting an int, string, bool, etc I use the following and cast the type of the return value:
public string ProcessRequestWithValue()
{
var response = _client.Execute(_request);
if (response.ErrorException != null)
{
throw response.ErrorException;
}
return response.Content;
}
Hope this helps!
Related
This question already has answers here:
Where can you find model binding errors in ASP.NET Core MVC?
(2 answers)
Closed 4 years ago.
I am creating a web api that receives data in a POST request in form of a JSON object in the body.
The real DataObj has many more fields so I simplify it to the following to show a specific sample where parsing must fail:
public class DataObj
{
public int Value { get; set; }
}
[HttpPost]
public async Task<IActionResult> SubTables([FromBody] DataObj data)
{
if (data == null)
{
string parsingErrorDetails = "";
// ? how can I check which kind of parsing erros happend?
return BadRequest("Failed to parse JSON with error: " + parsingErrorDetails);
}
..
}
Typically if you post valid JSON data to the service (like { "value": 1 } it just works fine.
But in the above example a valid JSON body would also be one like { "value": 6123456789 } parsing fails because the value exceeds Int32.MaxValue.
In my case the body has an object with several fields which makes it complicated to analyze the problem if I just return 404 Bad Request.
My goal is that I want to be able to report this specific problem back to the caller so that the caller has an easier option to analyze the root cause of the call.
Best without loosing the option to use [FromBody].
Is there a way to query details why the data object was null as in the sample above so that I can report it back to the caller?
I would check values on the setter properties of DataObj, throwing an exception in case the value doesn't fit.
public class DataObj
{
private int myInt;
public int MyInt{
get{ return myInt;}
set
{
if (value > int.MaxValue)
throw new ArgumentException("Invalid value for MyInt");
myInt = value;
}
}
I've created an API in .NET Core 2 using C#. It returns an ActionResult with a status code and string message. In another application, I call the API using Flurl. I can get the status code number, but I can't find a way to get the message. How do I get the message or what do I need to change in the API to put the message someway Flurl can get it?
Here's the code for the API. The "message" in this example is "Sorry!".
[HttpPost("{orderID}/SendEmail")]
[Produces("application/json", Type = typeof(string))]
public ActionResult Post(int orderID)
{
return StatusCode(500, "Sorry!");
}
Here's the code in another app calling the API. I can get the status code number (500) using (int)getRespParams.StatusCode and the status code text (InternalError) using getRespParams.StatusCode, but how do I get the "Sorry!" message?
var getRespParams = await $"http://localhost:1234/api/Orders/{orderID}/SendEmail".PostUrlEncodedAsync();
int statusCodeNumber = (int)getRespParams.StatusCode;
PostUrlEncodedAsync returns an HttpResponseMessage object. To get the body as a string, just do this:
var message = await getRespParams.Content.ReadAsStringAsync();
One thing to note is that Flurl throws an exception on non-2XX responses by default. (This is configurable). Often you only care about the status code if the call is unsuccessful, so a typical pattern is to use a try/catch block:
try {
var obj = await url
.PostAsync(...)
.ReceiveJson<MyResponseType>();
}
catch (FlurlHttpException ex) {
var status = ex.Call.HttpStatus;
var message = await ex.GetResponseStringAsync();
}
One advantage here is you can use Flurl's ReceiveJson to get the response body directly in successful cases, and get the error body (which is a different shape) separately in the catch block. That way you're not dealing with deserializing a "raw" HttpResponseMessage at all.
Consider this snippet from my REST client (Jersey 2.26). It's used to post objects and return the response object. If the REST server returns an error (status >= 400), then instead of returning an entity of type T I want to read an entity of type ErrorMessage and throw an exception containing the error message object.
protected <T> T post(final Class<T> type,
final Object entity,
final Map<String, Object> queryParams,
final String methodPath,
final Object... arguments) {
return postResponse(
getInvocationBuilderJson(methodPath,
queryParams,
arguments),
entity
).readEntity(type);
}
protected Response postResponse(final Invocation.Builder invocationBuilder,
final Object entity) {
return handleErrors(
invocationBuilder.post(Entity.entity(entity,
MediaType.APPLICATION_JSON_TYPE))
);
}
protected Response handleErrors(final Response response) {
if (response.getStatus() >= 400) {
throw new InvocationException(response.readEntity(ErrorMessage.class));
}
return response;
}
If no error occurs (status < 400), then my object of type T is returned as expected. However, when an error does occur, response.readEntity(ErrorMessage.class) returns null. But (and this is the strange part), this does get me data (at the handleErrors method):
byte[] data = readAllBytes((InputStream) response.getEntity());
I could use that and deserialize it manually.. but I would first like to know if there are any options to fix this without implementing workarounds.
After switching from the default MOXy JSON (de)serializer (we now are using a GSON provider) the problem was resolved.
We recently had a similar issue with JSON-B. There is turned out we had to add a getter and setter on our error object on order to (de)serialize the object.
I am having Json like this,I wanna get/read "responseCode" using Jackson,How to do this?
{
"successful":false,
"responseMessage":"direct address error: direct address is taken",
"responseCode":4610
}
Multiple ways. One is to define matching Java class with just that one field:
// either mark to ignore anything else; or specify field/setter for every property, both work
#JsonIgnoreProperties(ignoreUnknown=true)
public class Response {
public int responseCode;
}
Response resp = new ObjectMapper().readValue(json, Response.class);
int responseCode = resp.responseCode;
or, using Tree Model
JsonNode root = new ObjectMapper().readTree(json);
int responseCode = root.path("responseCode)".asIntValue();
I am using jersey to create rest api. I have GET api which returns xml or json representation of an object instance using JaXB. Everything is fine as long as I can get this instance based on id and return it. But when I don't find instance what should I return. I know 404 response has to be returned. But my method already returns a given type. So how do I setup 404 status is response?
Here is simplified version of my method
#GET
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public GameDAO getGameState(#PathParam("gameId") String gameId)
{
//code to get game instance based on gameId
if(game != null)
{
GameDAO d = new GameDAO(game);
return d; //gets auto converted to xml or json
}
return null; //how to return not found response ?
}
A 404 response is what you want, and I think the best way to get there is by throwing a "not found" WebApplicationException. Here's an example:
throw new WebApplicationException(Response.Status.NOT_FOUND);
There are plenty of ways to customize the error handling; you can find more details in the Jersey docs: https://jersey.java.net/documentation/latest/representations.html