I am trying to expand my existing app to store user favorites of a specific object server side.
The App is using RestKit ~> 0.26.0 which has many GET calls setup using response descriptors. However when I make an inverse mapping for the request descriptor of a POST/DELETE call it seem to fail to result in any request body being made.
Request descriptor setup code:
// Code User Favorites Mapping
RKEntityMapping *codeFavoritesMapping = [RKEntityMapping mappingForEntityForName:@"Code" inManagedObjectStore:objectStore];
[codeFavoritesMapping setIdentificationAttributes:@[@"scheme", @"code"]];
[codeFavoritesMapping addAttributeMappingsFromArray:@[ @"cuid", @"code", @"scheme" ]];
[codeFavoritesMapping addAttributeMappingsFromDictionary:@{ @"shortdesc" : @"text" }];
// POST/DELETE
[[RKObjectManager sharedManager] addRequestDescriptor:[RKRequestDescriptor requestDescriptorWithMapping:[codeFavoritesMapping inverseMapping]
objectClass:[Code class]
rootKeyPath:nil
method:(RKRequestMethodPOST | RKRequestMethodDELETE)]];
// GET
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:codeFavoritesMapping
method:RKRequestMethodGET
pathPattern:kRestKitEndpointCodeFavorites
keyPath:API_WRAPER_KEYPATH
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
Note that the GET being setup above does function as expected.
Here are the POST/DELETE calls themselves:
if (isFavorite) { // Removing from favorite list
...
// Delete favorite server side
[[RKObjectManager sharedManager] deleteObject:_code path:kRestKitEndpointCodeFavorites parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"Deleted code: %@", _code.code);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Failed to delete code: %@", _code.code);
}];
} else { // Adding to favorite list
...
// Add favorite server side
[[RKObjectManager sharedManager] postObject:_code path:kRestKitEndpointCodeFavorites parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(@"Added code: %@", _code.code);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"Failed to add code: %@", _code.code);
}];
}
From what I understand this should result in both the POST/DELETE calls sending a request body of something like:
{"code":"101","scheme":"scheme1","cuid":"123456789","shortdesc":"Basic code sample"}
However, the server and RestKit logs show that nothing gets sent over. Maybe I am missing something basic?
Let me know what you think might be the issue or if you need any further information/clarification. Thank you for your time!
Edit: Adding RestKit Log info
POST:
I restkit.network:RKObjectRequestOperation.m:137 POST 'https://mobile-api.myapp.com:8000/v2/codes'
D restkit.network:RKObjectRequestOperation.m:138 request.headers={
Accept = "application/json";
"Accept-Language" = "en-US;q=1";
Authorization = "Basic ZHJ1bXBsZW1kaHRtbDpzY3JpYmU=";
"User-Agent" = "MyApp/1.2.3.4 (iPod touch; iOS 9.3.2; Scale/2.00)";
}
I restkit.network:RKResponseMapperOperation.m:515 Non-successful status code encountered: performing mapping with nil target object.
E restkit.network:RKObjectRequestOperation.m:175 POST 'https://mobile-api.myapp.com:8000/v2/codes' (400 Bad Request / 0 objects) [request=3.4962s mapping=0.0000s total=3.5758s]: Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched." UserInfo={DetailedErrors=(
), NSLocalizedFailureReason=The mapping operation was unable to find any nested object representations at the key paths searched:
The representation inputted to the mapper was found to contain nested object representations at the following key paths: code, developerMessage, message, moreInfo, property, status
This likely indicates that you have misconfigured the key paths for your mappings., NSLocalizedDescription=No mappable object representations were found at the key paths searched., keyPath=null}
T restkit.network:RKObjectRequestOperation.m:182 response.body={"status":400,"code":0,"property":"","message":"Invalid data","developerMessage":"invalid scheme","moreInfo":""}
Failed to add code: 101
DELETE:
I restkit.network:RKObjectRequestOperation.m:137 DELETE 'https://mobile-api.myapp.com:8000/v2/codes'
D restkit.network:RKObjectRequestOperation.m:138 request.headers={
Accept = "application/json";
"Accept-Language" = "en-US;q=1";
Authorization = "Basic ZHJ1bXBsZW1kaHRtbDpzY3JpYmU=";
"User-Agent" = "MyApp/1.2.3.4 (iPod touch; iOS 9.3.2; Scale/2.00)";
}
I restkit.network:RKResponseMapperOperation.m:515 Non-successful status code encountered: performing mapping with nil target object.
I restkit.network:RKObjectRequestOperation.m:178 DELETE 'https://mobile-api.myapp.com:8000/v2/codes' (400 Bad Request / 0 objects) [request=2.0675s mapping=0.0057s total=2.1261s]
D restkit.network:RKObjectRequestOperation.m:179 response.headers={
Connection = close;
"Content-Length" = 112;
"Content-Type" = "application/json; charset=utf-8";
Date = "Fri, 24 Jun 2016 17:22:09 GMT";
Etag = "W/\"70-nu03kd5Vpszkdw25X+pmaQ\"";
Vary = "Accept-Encoding";
"x-powered-by" = Express;
}
T restkit.network:RKObjectRequestOperation.m:182 response.body={"status":400,"code":0,"property":"","message":"Invalid data","developerMessage":"invalid scheme","moreInfo":""}
Deleted code: 101
Edit: Response to Wain's question
I have checked what the server received, however it is nothing but an empty request body sent. I have tried passing the dictionary for the object, hand coded, in the parameter portion of the two POST/DELETE calls.
Hand coding the POST parameters does send as expected, and the resulting request body is exactly as desired. However, result from hand coding the DELETE call causes the hand coded parameter to become a part of the url query string; i.e. https://mobile-api.myapp.com:8000/v2/codes?code=101&scheme=scheme1&cuid=123456789&shortdesc=Basic code sample
RestKit MIME type setup:
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:API_HOST_NAME]];
[RKObjectManager setSharedManager:objectManager];
[objectManager setRequestSerializationMIMEType:RKMIMETypeJSON];
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeJSON];