I'm trying to update some fields with body parametres
NSString *requestString = [NSString stringWithFormat:#"%#/auth/password", self.baseURL ];
[[self managerWithHeaders] PUT:requestString parameters:#{#"foo":#"bar"} success:^(NSURLSessionDataTask *task,id responseObject) {
NSLog(#"%#",responseObject);
} failure:^(NSURLSessionDataTask *task,NSError *error) {
if(failure) failure(error, [self getErrorMessageWithCode:error.code]);
}];
on server this method getting
{"foo"=>"bar", *"password"=>{"foo"=>"bar"}}
But Password is a method name. Why PUT method trying update this parameters?
P.S when i send this request with string (#"%#/auth/password?foo=bar") everything is ok.
As mentioned in the comments; a PUT request puts the parameters into the HTTPBody and not into the URL like a GET request would.
So, add them to your parameters and not to the URL part. Something like this:
[[self managerWithHeaders] PUT:#"example.com/auth parameters:#{#"foo":#"bar", #"password" : #"sdfsdfsff"} success:^(NSURLSessionDataTask *task,id responseObject) {
NSLog(#"%#",responseObject);
} failure:^(NSURLSessionDataTask *task,NSError *error) {
if(failure) failure(error, [self getErrorMessageWithCode:error.code]);
}];
Don't include parameters as part of the URL for PUT requests
Related
I am working on an app where I have AFNetworking fetching JSON requests from the my server. Now JSON is dynamically created based upon the POST variables I send from my app.
I was wondering when I get the following error message
JSON text did not start with array or object and option to allow fragments not set.
Is there a way to adapt my code so that I can actually see in the logger what the returned JSON request looks like. I have a feeling that there is a warning popping up in my PHP that is throwing off the JSON but I am not sure what it is.
Here is my code, it would make it so much easier if I could lets say NSLog the body content.
[manager POST:#"__MY__URL__" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
} progress:nil success:^(NSURLSessionDataTask *operation, id responseObject) {
NSLog(#"Success: %#", responseObject);
if([[responseObject objectForKey:#"state"] isEqualToString:#"success"]){
//[self performSegueWithIdentifier:#"client_choose_ad" sender:self];
}else {
[self alertError:#"Unable To Create Advert" alertMessage:[responseObject objectForKey:#"message"]];
}
} failure:^(NSURLSessionDataTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Maybe printing the raw data of the request is what you are looking for.
How to print AFNetworking request as RAW data
I have a scenario where I need to quiet refresh auth token (relogin) again if it expired when I accessing other API but I'm having a hard time thinking how to code this without creating redundant codes for every APIs even though the flow is similar.
When user has expired auth token > call paid API A (return 401 unauthorised) > relogin again > call paid API A (run successfully)
I'm having difficult in wrapping my mind to call paid API A the second time with less code and not falling into infinite loop trap. Is there any method useful for this case like NSNotification center?
Note: I need to use API in this format from AFNetworkinglogin
- (NSURLSessionDataTask *)getApiA:(CallbackBlock)block{
CallbackBlock _block = [block copy];
NSString *urlString = [[NSURL URLWithString:GET_API_A_URL relativeToURL:[NSURL URLWithString:HOME_URL]] absoluteString];
return [self GET:urlString parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSDictionary *response = (NSDictionary *)responseObject;
BLOCK_SAFE_RUN(block, response, nil, task);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if([self unauthorizedAccess:task]){ //401
***//call Login once again > run getApiA again***
}else if ([self forbiddenAccess:task]){ //403
}
BLOCK_SAFE_RUN(block, nil, error, task);
}];
}
If i get it right you could split it into 2 methods. And pass a bool for trying again. e.g.:
- (NSURLSessionDataTask *)getApiA:(id)block {
NSString *urlString = [[NSURL URLWithString:GET_API_A_URL relativeToURL:[NSURL URLWithString:HOME_URL]] absoluteString];
return [self doApiACallWithURL:urlString firstTry:YES completion:block];
}
- (NSURLSessionDataTask *)doApiACallWithURL:(NSString *)url firstTry:(BOOL)first completion:(CallbackBlock)completion {
__weak typeof(self) wself = self;
return [self GET:urlString parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) {
NSDictionary *response = (NSDictionary *)responseObject;
BLOCK_SAFE_RUN(block, response, nil, task);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
if ([wself unauthorizedAccess:task]) { //401
if (first) {
[wself doApiACallWithURL:url firstTry:NO completion:completion];
}
} else if ([wself forbiddenAccess:task]) { //403
}
BLOCK_SAFE_RUN(block, nil, error, task);
}];
}
and use a weak self for blocks is in most cases a good idea.
I was wondering, is there a file format that allows you to store keys and values, and some api that lets you read said file from a web server into a NSDictionary easily? I'm just trying to store 5 or so values associated with keys in a file on the web, so looking for something simple.
I know how to read a simple text file into an NSString, but I was wondering if there is something that lets me do what I described above easily / more efficiently without having to manually prepare the file myself and then write the code to tokenize it, etc.
The file format you need is json. The API you need is AFNetworking. Here is the sample which connect to a server and parse that json to NSDictionary.
//send son info to server
NSDictionary* json = #{
kUserTokenKey : [SOLUser currentUser].token,
kMarkerUserMarkPayIDKey : markerUserMark.objectID,
kCardMarkerPayIDKey : card.objectID,
kCardZipCodeKey: zipCode
};
//create a request url
NSString* requestURL = [NSString stringWithFormat:#"%#%#",kSOLServicesURL,kSOLServicesMarkerPay];
//AFNetworking block to call server api
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:requestURL parameters:json success:^(NSURLSessionDataTask *task, id responseObject) {
[manager invalidateSessionCancelingTasks:YES];
//Recieving object from server and pass to json
NSDictionary* obj = responseObject;
if ([obj[kAPIStatusKey] isEqualToString:kAPIStatusSuccessKey]) {
if (completion) completion(nil);
} else {
NSError* error = [NSError errorWithMessage:obj[kAPIDataKey] code:0];
if (completion) completion(error);
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
[manager invalidateSessionCancelingTasks:YES];
LBLog(#"Error: %#", error);
if (completion) completion(error);
}];
I can't figure out a way of downloading objects in a queue using AFNetworking 2.0.
I have an array of ID's. I want to make a request with the last object from array, when this request is completed, make a second request, third request, and so on.. But if at least one request fails, I need to stop.
while ([dataArray count] > 0) {
[[APIClient sharedClient] POST:#"/api/my_object.json" parameters:#{#"obj":[dataArray lastObject]} success:^(NSURLSessionDataTask *task, id responseObject) {
[dataArray removeLastObject];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
break;
}];
}
I Know this is not right, because i get async callbacks. So Maybe anyone could suggest of how to achieve this? Maybe using queues or something like that?
Thanks in advance for any help!
Your solution is to make one request at the time. That means, start a new request only when you get a result from the last one.
Something like this:
-(void) makeNextRequest {
__typeof__ (self) __weak weakSelf = self;
[[APIClient sharedClient] POST:#"/api/my_object.json" parameters:#{#"obj":[dataArray lastObject]} success:^(NSURLSessionDataTask *task, id responseObject) {
[dataArray removeLastObject];
[weakSelf makeNextRequest];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
}];
}
I'm sending a NSMutalbeDictionary User with the correct information.
I have sending post using these two methods.
+ (void)loginUsers:(NSMutableDictionary*)user {
NSString *endpoint = #"api/users/sign_in";
[self postEndpoint:endpoint params:user completionBlock:^(TSystemsResponse *response) {
}];
}
+ (void)postEndpoint:(NSString *)endpoint params:(NSMutableDictionary *)params completionBlock:(void (^)(TSystemsResponse *response))completionBlock {
[[TSystemsAPIClient sharedClient] postPath:[NSString stringWithFormat:#"/%#", endpoint] parameters:params success:^(AFHTTPRequestOperation *request, id responseObject) {
TSystemsResponse *resp = [[TSystemsResponse alloc] initWithDictionary:responseObject];
completionBlock(resp);
} failure:^(AFHTTPRequestOperation *request, NSError *error) {
NSLog(#"Request to /%# FAILED: %#", endpoint, error);
completionBlock(nil);
}];
}
I'm getting a response from the server that says the following
{
"success": false,
"message": "Missing user parameter"
}
So i'm thinking that I'm not sending the information through correctly. The API call works in Post man.
Double check the params variable actually has the key "user" and not uppercased:
NSLog(#"%#", params);
[self postEndpoint:endpoint params:params completionBlock:nil];
If that is not the case you have to show us the innards of TSystemsAPIClient postPath:parameters:success: method.