de-serialization of response when the request may return different objects - restsharp

I'm using RestSharp to invoke an API. I have the basic functionality working pretty well now, I can call RestClient.Execute(new RestRequest("/something")). The server returns JSON which is mapped over to a class I created. This all works great.
However... if the call fails, the server will return a different object. It returns an error object on failure which, of course, won't match the type specified for success.
Is there a way to deal with a request which may either return the normal answer or an error object?

Got it working. What I'm seeing is that if the call fails, IRestResponse.IsSuccessful is false and the response content JSON string is the error object instead of the normal response.
So, after calling RestClient.Execute, if IsSuccessful is false, I then call RestClient.Deserialize using an error object C# class.
In this way if the call succeeds, I get the regular de-serialized object, if the call fails, I get the API's error object which I can then throw as an exception or otherwise handle.

Related

FromForm annotation not supported in MapPost()ed methods?

.NET 6, purely WebAPI project. I have an endpoint method that is expecting a urlencoded form in the POST data. The method is added to the routing table by app.MapPost("/myendpoint", MyClass.MyEndpoint) in the program's startup file; it's not in a controller. The method currently goes:
[Consumes("application/x-www-form-urlencoded")]
[HttpPost]
public static async Task<IResult> MyEndpoint([FromForm]FormData TheForm)
where FormData is a record with the expected form fields.
I've tried some other annotations. The framework just won't let me consume the form. When invoked, the method either returns HTTP error 415, or, in some iterations, an exception is thrown somewhere in the pipeline saying that "Expected a supported JSON media type but got "application/x-www-form-urlencoded"."
Is urlencoded form parameter binding even supported in WebAPI? I would even settle for the form contents as a string, won't mind parsing myself (HttpUtility.ParseQueryString to the rescue).
For the time being, I read Request.Body from the HTTP context' request body, but that's crude and also error prone, as the context is known to go poof sometimes in async methods.
EDIT: also tried placing .Accepts<FormData>("application/x-www-form-urlencoded") on the MapPost() line. Same result.
Tried replacing the body parameter with [FromBody]byte [] Body, [FromBody]string Body.

Bypassing Play's HttpErrorHandler for 4xx errors

I'm writing a microservice in Play. I'd like my controller to be able to generate client errors (4xx) with a particular JSON response body. However, Play's default HttpErrorHandler kicks in, and replaces my response body with an HTML document.
How can I have my response returned to the client untouched?
I have looked into providing a custom HttpErrorHandler, but this doesn't give access to the response that my controller had generated; the signature is:
def onClientError(request: RequestHeader, statusCode: Int, message: String): Future[Result]
Edit: I can no longer reproduce this problem. Now, the error handler doesn't kick in -- which is the behaviour I'd expect. Most likely some form of user confusion / error.
A client error is a condition which is caused by the client, and Play doesn't know how to handle. That includes malformed headers, non-existing resources (read : No route available for that path).
In all cases, this won't hit a controller : It's handled before it's routed. That also means there is no body that can be passed along.
If it does hit a controller, you're free to return a Result with the proper response code and body. If it doesn't hit a controller, and the error handler is invoked, you need to return a response based on the request itself.
An example of what you're trying to achieve would be handy, since it's a bi t unclear to me.

Exceptions and StatusCode in ASP.NET Core MVC

We have UseExceptionHandler (handle Exeptions) and UseStatusCodePages (handle StatusCode). Why in ASP.NET Core MVC we using StatusCodeResult than just handy extend Exception?
UseExceptionHandler is generally used to catch up unexpected errors and preset them in a more friendly manner to the user.
Whereas status codes are more important in REST API to signal the client the success or failure (and specific cause of the failure) of the specific operation.
Controller action should never throw exception and access a specific resource (i.e. db record) which doesn't exist you should return 404 (not found). When passed data is invalid rest apis return "400 bad request", on success 200. When new resource is created 201 (with "Location" header which contains the url to the new resource, see CreatedAtAction method of the controller class).
With views it works differently where you render the error directly into the HTML Code. You can also return status codes with MVC-esque view controllers and handle it with UseStatusCodePages (i.e. showing a generic NotFound.cshtml template for resources which don't exist).
Also your question sounds like you want to use exceptions to set status code, this is wrong for a couple of reasons.
Exceptions should be (as their name suggest) exceptional; Read: when something unexpected happens. For example if you try to withdraw a negative balance from your bank account and further processing it makes no sense or becomes impossible.
When you expect an error, you should return a result or handle it differently. For validations you should use Result classes (i.e. IdentityResult from ASP.NET Core Identity, which contains a Success property and a property which contains a list of error messages in case the operation or the validation fails).
Throwing and catching Exceptions is quite expensive, so they should really only be thrown when (as pointed above) something unexpected happens. Not finding a record is nothing unexpected.
(Ab)using exceptions for flow control (deciding which code path to execute) is just wrong. That's what if/switch and patterns like strategy pattern are for. Exceptions will just make the code unreadable and harder to maintain.

AFNetworking get Parameters from Operation

I am attempting to get the parameters for a POST request sent via the AFNetworking pod. However, I can't seem to get them. I am looping through the active operations with the below:
for(AFHTTPRequestOperation* operation in manager.operationQueue.operations){
NSLog(#"%#",operation.request.URL.path);
}
However, I can't get the parameters. I've tried using operation.request.URL.parameterString, but since it is POST, the string is null. Anyone know how to get these? I'd like to collect them so that I can cancel requests that are specific to the path and parameters sent, ensuring I'll get down to just the single request I need to cancel.
I ended up going about this a different way. I created a class that handled all the AFNetworking path calls. In this class is a dictionary which stored an integer id for the call and the operation. As the operations complete or fail, they are removed. The integer id is passed back to the calling object, allowing for unique access for canceling requests or polling.

Dojo informative message sent after xhrPost

Let's say that a request is sent to server via xhrPost and server finds that request needs more information to be processed (for example a variable is missing), so, a response is sent back to client informing that request may have not been completely processed and this message is shown in a dialog box.
I was doing it sending from server an HTTP 202 status code, which I believe is not correct, and treating it on load function, where this message was displayed on a dialog box. But if I respond with some HTTP error code (ex: 400) the error is displayed in console (Note: in this case the message is treated in error function), as well as in my dialog box.
What is the best and correct way to do it?
Note that it is called a load handler, not a success handler.
The load hander is for valid, well formatted responses. These can contain a verity of status codes generated by your server side app that indicates success, failure, or something in between.
The error is just that, the server blew up while trying to process the request and whatever you get back is probably not something your widget was written to expect. For this reason, I recommend using the same error handler across your whole app.
The dojo documentation states:
Sometimes xhrGet calls will fail. Often these are 404 errors or server errors such as 500. The error parameter is another callback function that is only invoked when an error occurs. This allows you to control what happens when an error occurs without having to put a lot of logic into your load function to check for error conditions. The first parameter passed to the error function is a JavaScript Error object indicating what the failure was. Dojo doc