RESTKit communication error - objective-c

I am trying to consume an XML web service through RESTKit.
I am able to connect to the service but I am receiving an error back as follows:
error=Error Domain=AFNetworkingErrorDomain Code=-1016 "Expected content type (null), got application/xml"
I have tried setting the content type header as follows but still not getting any change:
AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[client setDefaultHeader:#"Content-Type" value:RKMIMETypeXML];
Hopefully somebody can help.
I have included the code I am using to make the request below:
NSURL *baseURL = [NSURL URLWithString:#"http://someaddress/"];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:baseURL];
[objectManager setRequestSerializationMIMEType:RKMIMETypeXML];
[objectManager setAcceptHeaderWithMIMEType:RKMIMETypeXML];
RKObjectMapping *recipeMapping = [RKObjectMapping mappingForClass:[Recipe class]];
[recipeMapping addAttributeMappingsFromDictionary:#{
#"articleid" : #"ArticleId",
#"title" : #"Title",
#"url" : #"URL"
}];
// Register our mappings with the provider using a response descriptor
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:recipeMapping
pathPattern:nil
keyPath:#"Recipes"
statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager getObjectsAtPath:#"some/path/"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSArray *recipes = [mappingResult array];
NSLog(#"Loaded statuses: %#", recipes);
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"Hit error: %#", [error localizedDescription]);
}];
The problem is that I am still getting the Expected content type (null), got application/xml error message.
Furthermore, I have made a call to the service URL with via a very quick and easy sample ASIHTTP app and this is successful. I must be missing something fundamental.
Thanks

Like Martin mentioned you don't need to talk to the AFHTTPClient directly as this point.
RKObjectManager* manager = [RKObjectManager managerWithBaseURL:baseURL];
[manager setRequestSerializationMIMEType:#"application/xml"];
[manager setAcceptHeaderWithMIMEType:#"application/xml"];

Related

RestKit - Response descriptor not added

I use RestKit version 0.26 and try to map a response to core data
This is the code I use for the code I use to built the request and Descriptor:
-(void)getProductListProductWithPageNumber: (int) pageNumber managedObjectStore: (RKManagedObjectStore *)managedObjectStore {
// initialize AFNetworking HTTPClient
NSURL *baseURL = [NSURL URLWithString:#"https://server.com"];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
objectManager.managedObjectStore = managedObjectStore;
RKResponseDescriptor *productListrResponseDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:[[CategoricalSystemDownloadManager sharedDownloadManager] getCDProductListProductMapping:managedObjectStore]
method:RKRequestMethodGET
pathPattern:#"/PLController/plProducts/:"
keyPath:nil
statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:productListrResponseDescriptor];
[objectManager getObjectsAtPath:[NSString stringWithFormat:#"/PLController/plProducts/currentResponseBody-%d", pageNumber]
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
}
The mapped JSON does is an array -> key path nil, right?
It looks like this:
[
{
"productId": 240,
"brandId": 69
}
]
This is the error
which failed to match all (0) response descriptors
I messed up the pathPattern. It should be /PLController/plProducts/:currentResponseBody

Parsing of NSDictionary of NSArray

I am using Restkit API to parse a JSON Reply, which I have received from my webserver. The reply from the webserver is in this form.scre
JSON reply is this
{"Menu Items":[
{
"ID":393,
"Title":"Lentil Soup",
"Description":"This is extremely tasty",
"Image":"Lentil_1.png"
},
{
"ID":392,
"Title":"Chicken Tortilla Soup",
"Description":"Quick. Simple. Delicious.":"$20",
"Image":"Tortilla_3.png"
}
]
}
I am using the below code to get the response, but fails to get any response.
NSURL *baseURL = [NSURL URLWithString:#"http://URL.com"];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL]; // init by url
[client setDefaultHeader:#"Accept" value:RKMIMETypeJSON];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"text/html"];
//set up restkit
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
//setup object mapping
//addAttributeMappingsFromArray is a shortcut method to use when the JSON and your data model share the same keys, which is “name” in your case.
RKObjectMapping* boyMapping = [RKObjectMapping mappingForClass:[ListItem class] ];
[boyMapping addAttributeMappingsFromArray:#[#"ID"]];
// register mappings with the provider using a response descriptor
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:boyMapping
method:RKRequestMethodAny
pathPattern:#"/demo/restaurant/app/menu_lists.php"
keyPath:#"Menu Items"
statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
NSDictionary *parameterDict = [NSDictionary dictionaryWithObjectsAndKeys:_slugString, #"item_slug", nil];
[[RKObjectManager sharedManager] getObjectsAtPath:#"/demo/restaurant/app/menu_lists.php"
parameters:parameterDict
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
_menuItems = mappingResult.array;
NSLog(#"menuItems is %#", _menuItems);
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"What do you mean by 'there is no coffee?': %#", error);
}];
every time it go to the failure Block.
(assuming the response received has a status code of 200)
You create an object manager:
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
then you configure it. But, then you try to use it with:
[[RKObjectManager sharedManager] getObjectsAtPath:...
and this is using a different instance that has been created somewhere else in the code and doesn't have any of the configuration you set on objectManager.
You need to reorganise your code to ensure you create and appropriately use your object manager(s).

How to POST a simple object's data to Server using RestKit 0.20

I am new in RestKit. I did not find a proper documentation or tutorial to send simple object data to Restful API.
Here is my problem in detail.
I have a class with name User having two properties for now: email and password.
I want to send them to server using RestKit 0.20.
I found some tutorials but all of them are outdated for RestKit v 0.10. I found this question but this is outdated as well. There is no sharedInstance selector of class RKObjectManager in RestKit 0.20 but sharedManager.
Any help would be great.
Finally I found the solution. Thanks #Mateusz for helping me out.
Here is the solution.
// Construct a request mapping for User
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:#{ #"email": #"email", #"password": #"password" }];
// construct a response mapping for User
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[User class]];
[responseMapping addAttributeMappingsFromDictionary:#{#"email": #"email", #"password": #"password", #"guid": #"guid"}];
RKRequestDescriptor *req = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[User class] rootKeyPath:#"user" method:RKRequestMethodPOST];
RKResponseDescriptor *res = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping method:RKRequestMethodAny pathPattern:nil keyPath:#"user" statusCodes:[NSIndexSet indexSetWithIndex:200]];
// Register our descriptors with a manager
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"http://localhost/api/user/"]];
[manager addRequestDescriptor:req];
[manager addResponseDescriptor:res];
// preparing sending User object
User *user = [User new];
user.email = #"example#example.com";
user.password = #"password";
NSLog(#"user email : %#", user.email);
[manager postObject:user path:#"user" parameters:#{#"api_key": MY_API_KEY} success:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
NSArray *arr = [result array];
User *temp= [arr objectAtIndex:0];
NSLog(#"SUCCESS ---------------------------- User's email: %#", temp.email);
NSLog(#"User's guid: %#", temp.guid);
// NSLog(#"--------- - --- -- - all resutl: %#", result);
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"failed post %#", error);
NSLog(#"%#",operation.description);
NSLog(#"%#",operation.HTTPRequestOperation.description);
}];

how to do a post using restkit

I am building an app using restkit to talk to my webservice. First of all I'm very new to this. What I need to do is post a username and password to my webservice so that the url looks like this.
http://urllinkcompany.com/en/webservice/company-user/login/apikey/key12345678?email=test#test.be&pwd=testtest
When I post this I get a json back. This json contains an status code. status = 200 --> OK
Status = 404 --> NOT ok
Now I tried to post something and NSLog this status code.
- (IBAction)login:(id)sender {
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Person class]];
[mapping addAttributeMappingsFromDictionary:#{
#"data.user.cu_email": #"cu_email",
}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping pathPattern:nil keyPath:nil statusCodes:nil];
NSString *baseUrl = #"http://urllinkcompany.com/en/webservice/company-user/login/apikey/key12345678?";
NSString *strUrl = [NSString stringWithFormat:#"%#email=%#&pwd=%#",baseUrl,_txtLogin.text,_txtPass.text];
NSURL *url = [NSURL URLWithString:strUrl];
NSLog(#"url is: %#",strUrl);
NSURLRequest *request = [NSURLRequest requestWithURL:url];
RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
NSLog(#"data result is %#", [result valueForKeyPath:#"data.status"]);
} failure:nil];
}
But I am getting this error.
E restkit.network:RKObjectRequestOperation.m:285 Object request failed: Underlying HTTP request operation failed with error: Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x1ed57c50 {NSUnderlyingError=0x20161e70 "bad URL", NSLocalizedDescription=bad URL}
2013-01-07 11:48:51.407 Offitel2[22086:907] I restkit.network:RKHTTPRequestOperation.m:152 GET '(null)'
2013-01-07 11:48:51.408 Offitel2[22086:907] E restkit.network:RKHTTPRequestOperation.m:173 GET '(null)' (0) [0.0010 s]: Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x1ed57c50 {NSUnderlyingError=0x20161e70 "bad URL", NSLocalizedDescription=bad URL}
Could anybody help me with this?
Kind regards
EDIT:
Here's a version without RKClient
RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:[NSURL URLWithString:#"http://urllinkcompany.com/"]];
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Person class]];
[mapping addAttributeMappingsFromDictionary:#{
#"data.user.cu_email": #"cu_email",
}];
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:_txtLogin.text, #"email", _txtPass.text, #"pwd", nil];
[objectManager loadObjectsAtResourcePath:#"en/webservice/company-user/login/apikey/key12345678" delegate:self block:^(RKObjectLoader* loader) {
loader.objectMapping = mapping;
loader.method = RKRequestMethodPOST;
loader.params = params;
}];
And implement those two RKObjectLoaderDelegate methods:
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error

RestKit ios - put - json instead of form encoded

i am writing an ios app that uses restkit to communicate with a web server through Rest with JSON
i am able to use [[RKObjectManager sharedManager] loadObjectsAtResourcePath:path delegate:self] to get object from my web service as JSON, map it to obj-c object, it works fine
now i am trying to use: [[RKObjectManager sharedManager] putObject:obj delegate:self]; and this call sends an object to the web service as form encoded and not JSON
so my question is: how to configure the sharedManager (or the routeur?) to send with content type JSON instead of form encoded.
any code example much appreciated.
Thx!
The easiest way is to simply set the property when you initialize the object manager, like so:
RKObjectManager* objectManager = [RKObjectManager objectManagerWithBaseURL:#"http://url.com"];
objectManager.serializationMIMEType = RKMIMETypeJSON;
Evan is correct, but I've had to also make sure I am sending a JSON string, because I had a nested NSDictionay.
If you have a dictionary you want to send as a JSON string, here's how you can do it:
// create a JSON string from your NSDictionary
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];
NSString *jsonString = [[NSString alloc] init];
if (!jsonData) {
NSLog(#"Got an error: %#", error);
} else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
// make the post using the objectManager if you want to map the response to a model
RKObjectManager* objectManager = [RKObjectManager sharedManager];
[objectManager loadObjectsAtResourcePath:#"/api/" delegate:self block:^(RKObjectLoader* loader) {
loader.serializationMIMEType = RKMIMETypeJSON; // We want to send this request as JSON
loader.objectMapping = [objectManager.mappingProvider objectMappingForClass:[Plan class]];
loader.resourcePath = #"/api/";
loader.method = RKRequestMethodPOST;
loader.params = [RKRequestSerialization serializationWithData:[jsonString dataUsingEncoding:NSUTF8StringEncoding] MIMEType:RKMIMETypeJSON];
}];
Okay just found how to do it:
subclass RKRouter.h or just change in RKDynamicRouter.m
return [object propertiesForSerialization];
to
[RKJSONSerialization JSONSerializationWithObject:[object propertiesForSerialization]];
and RestKit generate JSON for putObject call
Create an Object Manager and set the property for matching the header in JSON format
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"http://mobile.com"]];
[objectManager addResponseDescriptorsFromArray:#[responseDescriptor]];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
You can change serializationMIMEType for individual requests by subclassing RKObjectManager and change implementation of requestWithObject:method:path:parameters: in subclassed manager.
Send request:
SubclassedObjectManager *manager = ...
[manager putObject:nil
path:pathString
parameters:parameters
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}
];
Modify MIMEType of request for PUT method:
- (NSMutableURLRequest *)requestWithObject:(id)object method:(RKRequestMethod)method path:(NSString *)path parameters:(NSDictionary *)parameters
{
NSMutableURLRequest *request = [super requestWithObject:object method:method path:path parameters:parameters];
if (method&RKRequestMethodPUT) {
NSError *error = nil;
NSData *serializedJSON = [RKMIMETypeSerialization dataFromObject:parameters MIMEType:RKMIMETypeJSON error:&error];
[request setValue:RKMIMETypeJSON forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:serializedJSON];
}
return request;
}