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
Related
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.
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];
When I make a POST request to my webservice, the following error is generated:
TinyTds::Error: Cannot insert the value NULL into column 'BankCD',
table 'SlotsMasterData.Master.Bank'; column does not allow nulls.
The server console displays the following:
From the above you can see that values exist for all attributes of my Bank object, but suddenly the reference to each is NULL when 'SELECT CAST(SCOPE IDENTITY() ... ' is performed.
This is my app code:
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:basePathToWebService]];
RKObjectMapping *bankMapping = [RKObjectMapping mappingForClass:[Banks class]];
NSDictionary *attributeMappingDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
#"BankID", #"bankID",
#"BankCD", #"bankCD",
#"BankName", #"bankName",
#"InsertSourceKey", #"insertSourceKey",
#"UpdateSourceKey", #"updateSourceKey",
#"Active", #"active",
nil];
[bankMapping addAttributeMappingsFromDictionary:attributeMappingDictionary];
RKObjectMapping *bankRequestMapping = [RKObjectMapping requestMapping];
[bankRequestMapping addAttributeMappingsFromDictionary:attributeMappingDictionary];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:bankMapping method:RKRequestMethodAny pathPattern:#"/banks" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:bankRequestMapping objectClass:[Banks class] rootKeyPath:nil method:RKRequestMethodAny];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager addRequestDescriptor:requestDescriptor];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"text/plain"];
//Post
[objectManager postObject:bank path:#"/banks" parameters:nil success:nil failure:nil];
Why is an attempt made to insert NULL values? How do I fix this? Thanks for your help!
bankRequestMapping should be declared as the inverse mapping of the bankMapping. As you have it at the moment the parameter names appear to be the wrong way around. You should use Charles to check what you are actually sending and that it matches what you expect.
i just update a content using restkit patchobject..when first time the method call invoked it leads success.but during second time call the same method ,the app crashes with NSInternal inconsistecy error.Cannot add adddescriptor for same class.thanks. below link also have same problem,but i dont know how to solve.
Restkit + Objective-c - Multiple calls to same web service
here is my method code
-(void)setContact:(int)_orgID :(int)_personID :(Person *)p1
{
AddressScreenViewController *addressView= [[AddressScreenViewController alloc]init];
addressView.mobileno = p1.mobile_phone;
addressView.workno = p1.work_phone;
addressView.homeno = p1.home_phone;
addressView.address1=p1.address1;
addressView.address2=p1.address2;
addressView.city=p1.city;
addressView.zip=p1.zip;
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
LoginAppDelegate * appDelegate = [[UIApplication sharedApplication] delegate];
RKObjectManager *objectManager = [RKObjectManager sharedManager];
[objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];
RKObjectMapping *personRequestMapping = [RKObjectMapping requestMapping];
[personRequestMapping addAttributeMappingsFromDictionary:#{ #"mobileno" : #"phone_numbers.mobile_number", #"workno" : # "phone_numbers.work_number" , #"homeno" :#"phone_numbers.home_number",#"address1":#"mailing_address.address1",#"address2":#"mailing_address.address2",#"city":#"mailing_address.city",#"zip":#"mailing_address.zip"}];
RKLogConfigureByName("RestKit", RKLogLevelWarning);
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
RKLogConfigureByName("RestKit/ObjectMapping", RKLogLevelTrace);
RKRequestDescriptor *requestDescriptor =[RKRequestDescriptor requestDescriptorWithMapping:personRequestMapping objectClass:[AddressScreenViewController class] rootKeyPath:#"person"];
[objectManager addRequestDescriptor:requestDescriptor];
NSString * orgPath = [NSString stringWithFormat:myurl];
[objectManager patchObject:addressView path:orgPath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
{
NSLog(#"result: %#", result);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"failuer function");
}];
}
The issue you are facing is because you are adding same request descriptor multiple times. You should set all request and response descriptor only once for example, in app delegate.
+ (void)setupDescriptors {
RKObjectManager *objectManager = [[AppDelegate appDelegate] objectManager];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
// Add Request Descriptors
//
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[Human rkEntityMappingForResponse:YES] method:RKRequestMethodAny pathPattern:nil keyPath:#"human" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKRequestDescriptor *userRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[User rkObjectMappingForRequest:YES] objectClass:[User class] rootKeyPath:#"user" method:RKRequestMethodAny];
RKRequestDescriptor *signupUserRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[User rkObjectMappingForSignupRequest:YES] objectClass:[User class] rootKeyPath:#"user" method:RKRequestMethodAny];
[objectManager addRequestDescriptorsFromArray:#[signupUserRequestDescriptor,userRequestDescriptor]];
RKResponseDescriptor *userResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[User rkEntityMappingForResponse:YES] method:RKRequestMethodAny pathPattern:nil keyPath:#"user" statusCodes:statusCodes];
[objectManager addResponseDescriptorsFromArray:#[userResponseDescriptor,responseDescriptor]];
}
But in some scenarios, you still want to add multiple request descriptor then this is done by dynamic mapping as answered by Author of REST Kit. Please see following link.
Adding two request descriptors for a given class in Restkit 0.2
I hope this helps.
You can't add a descriptor for the same key twice. You haven't added any code, but I know that you're adding all of your mappings and descriptors in the method where you're calling 'patch'. Don't...
Separate your configuration from your usage. Put all of your mapping and descriptor setup code into one method and call it once before you do anything else. Then, when you want to 'patch', call a different method which just does that and doesn't include any additional mappings.
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");
}]