iOS Swift 2 - Alamofire print response value when Failure - ios

I'm using Alamofire for my http requests but I'm not able to get error message from requests that don't pass validation
Alamofire.request(method, url, headers: headers, parameters: parameters, encoding: encoding)
.validate(statusCode: 200..<300)
.responseJSON { response in
switch response.result {
case .Success:
// response.result.value returns JSON
case .Failure(let error):
// response.result.value returns nil
}
}
How can I get data (JSON) if I get error code 400 and others. The API is sending the data in body even if the request was not successful.

As Following SaiCYLi, Only way to get response data is avoid using validate.
See Result.swift in Alamofire.
There is blocker.
public var value: Value? {
switch self {
case .Success(let value):
return value
case .Failure:
return nil
}
}
I wanted comment to you instead of answering. But I have reputation less than 50. Sorry.

just delete your validation of status code
Code:
Alamofire.request(method, url, headers: headers, parameters: parameters, encoding: encoding)
.responseJSON {
response in
let statusCode = response.response.statusCode
switch statusCode {
case 200..<300:
// Success
case 404:
// not found
default:
// something else
}
}

Related

getting data from AF.Request response

I need the data from the json response from my Post request call using Alamofire but I cannot access that data for some reason
I tried following along with Alamofire github documentation along with this post get data from AF responseJSON. but neither have helped me.
AF.request("https://mbd.cookcountysupernetwork.com/ap/swift_math_get.asp", method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
print("floop")
}
This is what I see when the code runs
success({
Operand = (
{
A = 12;
},
{
B = 25;
}
);
Operation = Multiply;
Result = 300;
})
so I know the json is there, i just need to access the "Result = 300" so I can set a text box to say "300". but I tried many different methods and I cannot access the information I need from response. Also i do not have a response.result.value which is what almost every post I see about this says to use.
You can access the Result value as,
AF.request("https://mbd.cookcountysupernetwork.com/ap/swift_math_get.asp", method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value):
if let json = value as? [String: Any] {
print(json["Result"] as? Int)
}
case .failure(let error):
print(error)
}
}

Alamofire (json, request, delay)

i have a json request and my problem is that the response from the server does not have time to come and because of this I get an error because I'm working with data (in viewdidload()) which is not yet available. I tried to read about synchronous and asynchronous requests but I don't understand how to do them.
in viewDidLoad() i call my fucn which is call to the my server and i wait a json, after executing the function, I start working with the data that should come , But the code does not wait for the moment when they come and go further. Can I specify a delay or something like that?
Alamofire.request(url, method: .post, parameters: params, encoding: JSONEncoding.default, headers: headers).responseJSON {
(response: DataResponse) in
switch(response.result) {
case .success(let value):
let json = JSON(value)
for index in 0 ..< json["items"].count {
let path = json["items"][index]
self.Data.append(ProfileModel())
self.Data[index].name = path["name"].stringValue
self.Data[index].email = path["email"].stringValue
self.Data[index].created = path["created"].double!
self.tableView.reloadData()
}
DispatchQueue.main.async {
}
case .failure(let error):
print(error)
break
}
}.resume()
}

Making a request in Alamofire 4.0 with a custom response

Having difficulty making a request in Alamofire 4.0. Previously I would use:
Code Snippet :
alamoManager.request(.GET, url, parameters: parameters, encoding: .url, headers: nil).responseObject { (response: Response<MyCustomResponse, NSError>) in
}
Where alamoManager is the old Manager object (now renamed SessionManager). However I can't see anything in the docs about how to pass a custom response (Conforms to Mappable). Has anybody achieved this? Any pointers would be really appreciated!
I used to type Alamofire 4.0 request like this:
import Alamofire
...
let parameters : Parameters = ["task":"setUser"]
Alamofire.request(url, parameters: parameters)
.validate()
.responseJSON { response in
//print(parameters), print(response.request), print(response.response), print(response.result)
switch response.result {
case .success:
let statusCode = (response.response?.statusCode)!
print("HTTP code #apiGetUser: \(statusCode)")
// ...
case .failure(let error):
// ...
}
}

Alamofire: Is there a way to get response data in case of Failure?

In Alamofire calling .validate() does automatic validation and passes status code 200...299 as success.
In case of failed API request server sends status code 400 and some internal error message and code in JSON to identify which kind of error is this. I couldn't find a way to get this JSON data in case status code is 400 under case .Failure in following example:
Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
.validate()
.responseJSON { response in
switch response.result {
case .Success:
print("Validation Successful")
case .Failure(let error):
print(error)
}
}
error doesn't contain response data. Is there anyway to get it?
If there is json data returned from the server on error, you should be able to get it from the response object, like:
print(response.result) // result of response serialization
if let JSON = response.result.value {
print("JSON: \(JSON)")
}
You can also subclass the ErrorType object returned by Alamofire:
public enum BackendError: ErrorType {
case Network(error: NSError)
case DataSerialization(reason: String)
case JSONSerialization(error: NSError)
case ObjectSerialization(reason: String)
case XMLSerialization(error: NSError)
}
This will give you more information about the error if you dont want to construct a custom error object to return. More on this from the Alamofire docs: https://github.com/Alamofire/Alamofire#handling-errors

Alamofire returns .Success on error HTTP status codes

I have a pretty simple scenario that I'm struggling with. I'm using Alamofire to register a user on a rest API. The first call to register is successful and the user can log in. The second call, when trying to register with the same email address should result in a HTTP status code 409 from the server. Alamofire, however, returns a .Success with an empty request and response. I have tested this this API with postman and it correctly returns a 409.
Why is Alamofire not returning .Failure(error), where the error has status code info etc?
Here is the call I run with the same input each time.
Alamofire.request(.POST, "http://localhost:8883/api/0.1/parent", parameters: registrationModel.getParentCandidateDictionary(), encoding: .JSON).response(completionHandler: { (req, res, d, e) -> Void in
print(req, res, d, e)
})
From the Alamofire manual:
Validation
By default, Alamofire treats any completed request to be successful,
regardless of the content of the response. Calling validate before a
response handler causes an error to be generated if the response had
an unacceptable status code or MIME type.
You can manually validate the status code using the validate method, again, from the manual:
Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.response { response in
print(response)
}
Or you can semi-automatically validate the status code and content-type using the validate with no arguments:
Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
.validate()
.responseJSON { response in
switch response.result {
case .success:
print("Validation Successful")
case .failure(let error):
print(error)
}
}
If using response, you can check the NSHTTPURLResponse parameter:
Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
.response { response in
if response.response?.statusCode == 409 {
// handle as appropriate
}
}
By default, 4xx status codes aren't treated as errors, but you can use validate to treat it as an such and then fold it into your broader error handling:
Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
.validate()
.response() { response in
guard response.error == nil else {
// handle error (including validate error) here, e.g.
if response.response?.statusCode == 409 {
// handle 409 here
}
return
}
// handle success here
}
Or, if using responseJSON:
Alamofire.request(urlString, method: .post, parameters: registrationModel.getParentCandidateDictionary(), encoding: JSONEncoding.default)
.validate()
.responseJSON() { response in
switch response.result {
case .failure:
// handle errors (including `validate` errors) here
if let statusCode = response.response?.statusCode {
if statusCode == 409 {
// handle 409 specific error here, if you want
}
}
case .success(let value):
// handle success here
print(value)
}
}
The above is Alamofire 4.x. See previous rendition of this answer for earlier versions of Alamofire.
if you use validate() you'll loose the error message from server, if you want to keep it, see this answer https://stackoverflow.com/a/36333378/1261547
Here is my code for AlamoFire error catching:
switch response.result {
case .success(let value):
completion(.success(value))
case .failure(var error):
var errorString: String?
if let data = response.data {
if let json = try? (JSONSerialization.jsonObject(with: data, options: []) as! [String: String]) {
errorString = json["error"]
}
}
let error = MyError(str: errorString!)
let x = error as Error
print(x.localizedDescription)
completion(.failure(x))
}
and the MyError class difinition:
class MyError: NSObject, LocalizedError {
var desc = ""
init(str: String) {
desc = str
}
override var description: String {
get {
return "MyError: \(desc)"
}
}
//You need to implement `errorDescription`, not `localizedDescription`.
var errorDescription: String? {
get {
return self.description
}
}
}

Resources