RESTKit - postObject:path:parameters:success:failure: method always fails - ios

I'm trying to send a POST request to a server. I'm using RESTKit with a request descriptor:
RKObjectMapping *messageRequestMapping = [RKObjectMapping requestMapping ];
[messageRequestMapping addAttributeMappingsFromArray:#[#"to", #"msg"]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:messageRequestMapping objectClass:[PostMessage class] rootKeyPath:nil method:RKRequestMethodAny];
[objectManager addRequestDescriptor:requestDescriptor];
and then I'm using postObject:path:parameters:success:failure:
PostMessage *postMessage = [PostMessage new];
postMessage.to = self.pickedPerson.name;
postMessage.msg = message.messgaeContent;
[[RKObjectManager sharedManager] postObject:postMessage path:#"/post" parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"SUCCES: message sent to server");
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"WARNING");
}];
The problem is that the failure block always gets called even though I see that the POST request got to the server successfully. When I test the same POST request with a simple REST client I get a status code of 200.
The error I get is:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No response descriptors match the response loaded." UserInfo=0x10c67adf0 {NSLocalizedFailureReason=A 200 response was loaded from the URL 'http://bla.com/post', which failed to match all (0) response descriptors:, NSErrorFailingURLStringKey=http://bla.com/post, NSErrorFailingURLKey=http://bla.com/post, NSUnderlyingError=0x10c60add0 "No mappable object representations were found at the key paths searched.", keyPath=null, NSLocalizedDescription=No response descriptors match the response loaded.}
I'm not sure if I have to set a responseDescriptor or not.
Can't I just set the expected status code like I do when setting a responseDescriptor?
EDIT:
I've added a response descriptor:
// message response after a post
RKObjectMapping *messageResponseForPostMapping = [RKObjectMapping mappingForClass:[PostMessage class]];
[messageResponseForPostMapping addAttributeMappingsFromArray:#[#"success"]];
RKResponseDescriptor *messageResponseForPostDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:messageResponseForPostMapping
method:RKRequestMethodPOST
pathPattern:#"post"
keyPath:#""
statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptorsFromArray:#[messageResponseDescriptor, personResponseDescriptor, messageResponseForPostDescriptor]];
as the server's response is:
{
"success" : "Message sent successfully."
}
and it still fails with the same error.

The error message tells you that
"No mappable object representations were found at the key paths searched."
So, either you gave an incorrect response descriptor, or you did not define one.
Giving a correct response descriptor should fix the issue.
This is an example response descriptor:
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:<YOURCLASSHERE>];
...
RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor
responseDescriptorWithMapping:mapping
method:RKRequestMethodPOST
pathPattern:path keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];

I didn't actually find what's wrong with my response descriptor.
My way of dealing with this was to change the response on the server. Instead of sending back a json file, the server now sends response code of 201, and RESTKit does not fail anymore.

Related

i want to POST data to server using RestKit,but it doesn't work and return 400

i want to Post data to server using RestKit. So i write my code according to https://github.com/RestKit/RestKit.
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[Post class]];
[responseMapping addAttributeMappingsFromArray:#[#"code", #"error",#"bookingNmbr"]];
//code,error,bookingNmbr are the parameters returned by server if i post data successfully
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *appliersDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:statusCodes];
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromArray:#[#"a", #"b", #"dcmnNmbr",#"type"]];
//a,b,dcmnNmbr,type are the parameters what i want to post to the server (into a json file). The structure of the json file is :{"appliers":[{"a":"F","b":9,"dcmnNmbr":"b","type":"c"}]}
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[Post class] rootKeyPath:#"appliers" method:RKRequestMethodAny];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:urlPost]];
[manager addRequestDescriptor:requestDescriptor];
[manager addResponseDescriptor:appliersDescriptor];
Post *post = [Post new];
post.a = #"aa";
post.b = 11;
post.dcmnNmbr = #"bb";
post.type = #"cc";
NSDictionary* params = [NSDictionary dictionaryWithObject:post forKey:#"appliers"];
[RKObjectManager sharedManager].requestSerializationMIMEType = RKMIMETypeJSON;
[manager postObject:params path:urlPost parameters:nil success:nil failure:nil];
The following is the result(code:400). It says that there is something wrong with the structure: "appliers not found".
E restkit.network:RKObjectRequestOperation.m:576 Object request failed: Underlying HTTP request operation failed with error: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1011 "Expected status code in (200-299), got 400" UserInfo=0xc8bd5b0 {NSLocalizedRecoverySuggestion={"code":-400,"error":"appliers Not Found"},
So could you please tell what's wrong with it.
This line:
NSDictionary* params = [NSDictionary dictionaryWithObject:post forKey:#"appliers"];
Isn't required (and you don't actually use).
The JSON that you show as your desired is an array of Post objects in a dictionary. At the moment you should get a dictionary in a dictionary. You can check this with Charles or a similar tool.
To get the array output that you're looking for, post an array:
[manager postObject:#[ post ] path:urlPost parameters:nil success:nil failure:nil];

Restkit failure: getting access to the json returned

I am using Restkit .20 and trying to get the error object returned in a failure block. I have tried both below and both return (null) for the error object.
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:
[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:#"errorMessage"]];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping
pathPattern:nil
keyPath:#"error" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
[self.objectManager addResponseDescriptorsFromArray:#[errorDescriptor]];
AND
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:#"error" toKeyPath:#"errorMessage"]];
[self.objectManager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:errorMapping pathPattern:nil keyPath:#"error" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)]];
This is in my failure block which prints out "errorMessage: (null)"
failure:^(RKObjectRequestOperation *operation, NSError *error)
{
NSLog(#"errorMessage: %#", [[error userInfo] objectForKey:RKObjectMapperErrorObjectsKey]);
}
Here is what is return from in the JSON from the server.
{
"status": "FAIL",
"user_errors": null,
"error": "Credit card type is not accepted by this merchant account.",
"user": null
}
An HTTP status code 201 is a success code, not an error code so your error mapping will not be tried (because of statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)).
So, update the server to send an appropriate status code. If you update the response descriptor to check 'successful' responses for errors I think it will work.

Restkit did not match pattern when response comes back

I have been seeing quite a few posts of this nature where a trailing '/' (or lack of) causes the pattern matching to fail.
My problem, however, is that there is no pattern to match against.
My error looks like this:
"No response descriptors match the response loaded." UserInfo=0xcb8a660 {NSErrorFailingURLStringKey=http://domain.herokuapp.com/auth/identity/callback,
NSLocalizedFailureReason=A 200 response was loaded from the URL 'http://domain.herokuapp.com/auth/identity/callback',
which failed to match all (3) response descriptors:
http://domain.herokuapp.com pathPattern=(null)
statusCodes=200-299>
failed to match: response path '/auth/identity/callback' did not match the path pattern '(null)'.
"did not match the path pattern '(null)'" is what I assume is the problem.
Setting up the objectmanager and HttpClient:
+ (void) fireUpRestkit
{
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
//base URL #"http://domain.herokuapp.com"
NSURL *baseURL = [[SCURLManager sharedInstance] baseURL];
AFHTTPClient * client = [AFHTTPClient clientWithBaseURL:baseURL];
[client setDefaultHeader:#"Accept" value:RKMIMETypeJSON];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
NSAssert(objectManager, #"objectManager did not instantiate correctly");
}
My request looks like this:
[[RKObjectManager sharedManager] postObject:user
path:/auth/identity/callback"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
My descriptors are setup like this:
RKObjectManager *objectManager = [RKObjectManager sharedManager];
RKObjectMapping *userMapping = [RKObjectMapping mappingForClass:[SCUserEntity class]];
[userMapping addAttributeMappingsFromDictionary:[SCUserEntity keyMapping]];
RKRequestDescriptor * requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userMapping.inverseMapping
objectClass:[SCUserEntity class]
rootKeyPath:nil
method:RKRequestMethodPOST];
RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager addRequestDescriptor:requestDescriptor];
I can't find the reason for the pattern I give when doing the postRequest does not seem to
be there when the request returns.
I have stepped through the buildResponseMappingsDictionary and subsequent matches~ methods. When the request is made they all return the correct descriptors, but when the request needs mapping it doesn't work.
I get a 200 OK from the server, I see both the request and response bodies and they seem correct.
Hope someone can help me spot the probably obvious missing part:)
It has nothing to do with the path pattern. It's the method.
You are using:
[[RKObjectManager sharedManager] postObject:user ...
but you have a response descriptor:
method:RKRequestMethodGET
i.e. one for POST and one for GET

RestKit 0.20 Error Domain=org.restkit.RestKit.ErrorDomain Code=-1016

I am trying to integrate RestKit 0.20 to My Project So for Example i am using google rss reader for sample project.
This is the response for Xml
/
/category>
&
This is the Xml from where i have to get the data.
RKObjectMapping* articleMapping = [RKObjectMapping mappingForClass:[News class]];
[articleMapping addAttributeMappingsFromDictionary:#{
#"title": #"title",
#"link": #"link",
#"guid": #"guid",
#"pubDate": #"pubDate",
#"description": #"description"
}];
NSURL* url = [[NSURL alloc]initWithString:#"http://news.google.com"];
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURL:url];
NSURLRequest* request = [objectManager requestWithObject:nil method:RKRequestMethodGET path:#"/?output=rss" parameters:nil];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:articleMapping pathPattern:nil keyPath:#"item" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[ responseDescriptor ]];
[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
RKLogInfo(#"Load collection of Articles: %#", mappingResult.array);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"Operation failed with error: %#", error);
}];
[objectRequestOperation start];
Above is the code i used to get data When i run the app i am getting the following error
I restkit.network:RKObjectRequestOperation.m:174 GET 'http://news.google.com/?output=rss'
2013-05-28 12:24:15.076 TestApp[8940:15203] E restkit.network:RKObjectRequestOperation.m:569 Object request failed: Underlying HTTP request operation failed with error: Error Domain=org.restkit.RestKit.ErrorDomain Code=-1016 "Expected content type {(
"application/xml",
"application/x-www-form-urlencoded",
"application/json"
)}, got application/rss+xml" UserInfo=0xa80a3d0 {NSLocalizedRecoverySuggestion=NFE/1.0Top Stories - Google News
Can any one help
As the exception says, RestKit is expecting one of:
"application/xml"
"application/x-www-form-urlencoded"
"application/json"
But it's receiving "application/rss+xml". You just need to tell RestKit what to expect.
You can ask RestKit if it already understands the mime type:
[RKMIMETypeSerialization registeredMIMETypes];
If not you'll need to register a serializer with RKMIMETypeSerialization.
And you can tell the object manager what mime type to expect:
[objectManager setAcceptHeaderWithMIMEType:#"application/rss+xml"];

How do I use RKResponseDescriptor with an id?

I am trying to create a RKResponseDescriptor to get people in a session.
I have a response descriptor for /sessions but I don't know how to create it to get the people in the sessions /sessions/20/people (/sessions/sessionID/people).
My session response descriptor is;
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:sessionsMapping
pathPattern:#"/sessions"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
The response descriptor for the people in the session is;
RKResponseDescriptor *clientInSessionResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:clientsInSessionMapping
pathPattern:#"/sessions/:sessionID/people"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
I keep getting the error, "Failed with error: No response descriptors match the response loaded."
I noticed in the documentation there is a lot of usage of the :id but can't seem to figure it out. Also, should I use a RKPathMatcher to build the path?
Any help would be greatly appreciated.
What I did was a parameter substitution when sending the request path. So in your case I would do the following:
NSString *idValue; // this is the sessionID value
NSString *path = [#"/sessions/:sessionID/people" stringByReplacingOccurrencesOfString:#":sessionID" withString:idValue];
[[RKObjectManager sharedManager] getObjectsAtPath:path parameters:nil success:^(RKObjectRequestOperation *operation,RKMappingResult *mappingResult)
{
// handle success
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"*** RK load FAIL");
}]

Resources