Difference between AFJSONRequestSerializer and AFHTTPRequestSerializer - ios

What actually is the reason that my request works for AFJSONRequestSerializer and doesnt for AFHTTPRequestSerializer?
I have set
responseSerializer.acceptableContentTypes?.insert("application/json")
for AFHTTPRequestSerializer and it doesn't work, but should.
I just send simple dictionary:
{
"approval_required" = 1;
birthdate = "2016-03-11";
gender = male;
name = Bartolo;
password = password1234;
username = "super user";
}
Here is similar question, but there is no explanation WHY it is like that.
Can anyone explain?

The acceptableContentTypes has little to do with the format of a request, ie whether it is HTTP request or JSON request. A request serializer's fundamental responsibility is to create a request in the specified format. Thus, the choice of requestSerializer dictates whether you are creating a HTTP request (e.g. a Content-Type of application/x-www-form-urlencoded) or JSON request (e.g. a Content-Type of application/json). The acceptableContentTypes merely allows the request to specify in what format(s) your app will accept responses. (And, frankly, you shouldn't specify acceptableContentTypes, but rather just use the correct responseSerializer.) But the request format and the accepted response format are two completely different things. In fact, it's not uncommon to have a web service that only accepts HTTP requests, and only provides JSON responses.
In your case, it sounds like you have a web service that is expecting a JSON request. When you specify AFHTTPRequestSerializer, the request will not be in JSON format and will likely not be understood. And specifying acceptableContentTypes does not alter the fact that the request, itself, isn't JSON.
By the way, tools like Charles or Wireshark are very useful for debugging network code, and would be illuminating in diagnosing the difference in these two types of requests. If you use one of these tools to watch the raw requests/responses, the difference will jump out at you.

Related

Siesta Service configureTransformer for URL decode models based upon parameters

I have an endpoint which supports post requests. The URL is the same for all requests but the parameters will be different for each request. It is basically a free-form query service when the client can formulate the query and fields that will be returned in the response. I would like to be able to define methods on the service which will represent specific queries and a model for each query. But I am uncertain as to how I would go about configuring the transformer for each "query based" endpoint.
Is there a way to accomplish this or is it best to simply work with a json dictionary?
Thanks...
I think that I found the solution to my problem and it was rather simple. It was just a matter of building the resource and supplying it to configureTransformer.
func getUserIds() -> Request {
let res = resource(endPoint)
.withParam("query", "SELECT id FROM users where status='Active'")
configureTransformer(res) {
try self.jsonDecoder.decode(UserIdResponse.self, from: $0.content)
}
return res.request(.post)
}

IOS/Objective-C/JSON:Obtain single value from Web Service in JSON

I want to obtain a single value from a web service in JSON, just a file name i.e. "picture.png"; based on some parameters passed.
Can IOS (I guess NSJSONSerialization JSONObjectWithData:) handle this single value in JSON or on the server side should I have it send a dictionary key as in {"pic": "picture.gif"}
If there is no picture, I am returning "nopic" so again should I have it return "error" or {"error": "nopic"}
I gather the various JSON specifications are conflicting on this point so my interest is just practical...how best to handle this case.
Thanks for any guidance on this

How can I use results of POST call to API to do another POST call

In a project I am working on, I am calling an https API with a POST request which gives me results as a JSON. I am doing the call with AlamoFire, and parsing this with SwiftJSON.
All goes according to plans, and the JSON is received and can be parsed. But now I want to use the values from the received JSON, and immediately do another call to the same API with a different path and use those values as parameters in the call.
At the moment I am posting a NSNotification and when that NSNotification is received I do the POST call to the other path for the details of the data. This works, but not very consistently.
I think that sometimes the data gets in the wrong sequence and the parameters might not be correct. About 80% of the time it works as expected.
Is this the way to work? Or is this not correct to do it with NSNotification? Any insights on this might help!
If you're using this notification pattern correctly, it should work 100% of the time, not 80% of the time. Or, more accurately, if the network connection or server response fails for reasons outside of your control, you should handle it gracefully. If you need help on that problem, update your question with MCVE and we'll see if we can help you.
In terms of a more efficient way to handle this overall process, the typical pattern would be to initiate the second request from inside the response closure of the first request.
Alamofire.request(.POST, url1, parameters: parameters1).response { request, response, data, error in
// create url2 and/or parameters2
Alamofire.request(.POST, url2, parameters: parameters2).response { request, response, data, error in
// do something with second request
}
}
One would generally only use the notification pattern if there is no reliable relationship between the two processes (e.g. when the first request was initiated, it has no reasonable way of possibly knowing which (if any) secondary request(s) will need to react in response to the first request.

iOS RestKit: How to make sure POST parameters are encoded in the request URL?

I'm trying to use RestKit because I'm expecting to make Core Data managed objects out of requests responses and it seemed like the framework was all about doing that and it seemed to be rather full featured.
But I'm having trouble getting my POST /user/login with parameters api_key=<value> (plus a separate JSON body) to end up a going out in a request like /user/login?api_key=<value>.
In the internals of RKObjectManager, requestWithMethod:path:parameters: does:
// NOTE: If the HTTP client has been subclasses, then the developer may be trying to perform signing on the request
NSDictionary *parametersForClient = [self.HTTPClient isMemberOfClass:[AFHTTPClient class]] ? nil : parameters;
request = [self.HTTPClient requestWithMethod:method path:path parameters:parametersForClient];
Do I have it right that this AFNetworking superclass method encodes parameters into the URL query? And does this mean the only way to ensure parameters are passed to that is to have my RKObjectManager use some subclass of AFHTTPClient?
And, according to the comment, supposedly this is only for sake of maybe a fringe case, something about request signing or something? Why is URL query-encoded request parameters not a common thing to do??
And getting things JSON encoded like I want does not seem to be as easy as I'd hoped either. Maybe it's a mistake for me to even try to use RestKit.

REST call may results in two different JSON objects. What design pattern should I use?

My web application makes a REST call. If the call is successful, it will return a 'weather' json object. If the call fails, it will return a json error object.
I want to make a class that parses the resulting JSON and returns a Weather object if the call succeeded and an Error Object if the call failed.
I'm thinking of using the Factory pattern but I'm not sure if that's a good approach because the two objects are very different from one another. What is a good way to design this code?
A common approach I use is to have Weather and Error both be Response objects and have a ResponseFactory create them.
I strongly encourage you to use proper HTTP codes when designing your service as they give a more general view of the state and success of each call.
You need first to check the result of the call, and then make a decision on how to handle it, with the possibility of handling all error codes with an error callback that returns an Error JSON object, and a success callback to return a Weather JSON object. You can use the HTTP codes to create a proper response and further subdivide the logic to return more specific errors, if needed.
The use of a Factory pattern seems overkill, specially given that the objects don't relate to each other.
It really depends on the environment you'll be using your API.
As a rule of thumb, rely on the HTTP code - if you get a 404 or a 500 of course you can't come up with a parsed response.
Format your error responses in a consistent way, e.g.
404 { "message" : "Resource not found" }
400 { "message" : "Wrong parameters given" }
So you know how to parse them.
If you get a 200 OKyou know everything was right, and you can parse your response with no problem at all.
Does the Content-Type header vary depending on the type of response?
As some have noted in their answers, the HTTP status code should be used to determine "Was there an error", but just as important is the interpretation of the content type returned.
Hoping the Content-Type header does vary, I would suggest using a registry of parsers, registered by content-type they handle, and then delegate to them to handle understanding how to convert a particular content type into the object you want. In Ruby, since you didn't specify a particular language:
case response.status:
when 200..299
return parsers[response.content_type].parse(response.body)
when 400..499
raise parsers[response.content_type].parse(response.body)
else
raise "Unhandled response status"
Doing so separates the two concerns:
Determining if there was an error
Parsing of content types into classes/types in your application.

Resources