Post request with raw body using NSURLSession - ios

I have stuck here. Below is my code for Post request with raw body using NSURLSession. I got response = NULL and no error.
NSString* stringRequest = #"https://chocudan.com/api/shops/by_ids";
NSURL* urlRequest = [NSURL URLWithString:stringRequest];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:urlRequest];
request.HTTPMethod = #"POST";
NSString* bodyRequest = #"563c268b84ba489c4729f149";
//I have to tried a base64 convert here but still not work.
//request.HTTPBody = [NSData base64DataFromString:bodyRequest];
request.HTTPBody = [bodyRequest dataUsingEncoding:NSUTF8StringEncoding];
NSURLSessionConfiguration* configureSession = [NSURLSessionConfiguration defaultSessionConfiguration];
configureSession.HTTPAdditionalHeaders = #{#"Content-Type" : #"application/json charset=utf-8",
#"Content-Lenght" : #"180"};
NSURLSession* session = [NSURLSession sessionWithConfiguration:configureSession];
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSHTTPURLResponse* respHttp = (NSHTTPURLResponse*) response;
if (!error && respHttp.statusCode == 200) {
NSDictionary* respondData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
NSLog(#"%#", respondData);
}else{
NSLog(#"%#", error);
}
}];
[dataTask resume];
I have to try with postman and everything work fine. This is pictures.
Thank in advance.

Try changing it too
NSArray* bodyArray = #[#"563c268b84ba489c4729f149"]
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:bodyArray
options:NSJSONWritingPrettyPrinted error:&error];
request.HTTPBody = jsonData;

My raw data was like :
{
"email":"test#gmail.com",
"password":"12345678"
}
and what I did is :
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setValue:#"test#gmail.com" forKey:#"email"];
[dict setValue:#"12345678" forKey:#"password"];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict
options:NSJSONWritingPrettyPrinted error:&error];
request.HTTPBody = jsonData;

This fixed it for me:
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.HTTPAdditionalHeaders = ["Content-Type" : "text/plain"]

I guess that it was not data that was null but respondData was null?
That is because your service sends an Array with exactly one Object. JSONSerialisation creates an NSArray from that with one NSDictionary in it. The dictionary has the keys _id, contact and so on.
So it is
NSArray* respondData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
BTW
NSHTTPURLResponse* respHttp = (NSHTTPURLResponse*) response;
does not make much of a sense but does not harm either.
With respect to the body of your request, see mihir's answer. He is just right.
It may help you understanding mihir's point when you do this:
NSString* bodyRequest = #"[563c268b84ba489c4729f149]";
However, this is rather quick & dirty but may help you understanding the principles. Once understood you will certainly follow mihir's suggestion.

If you want to post raw, and param is a format of NSString, you only need to do this:
NSData *param_data = [encry_str dataUsingEncoding:NSUTF8StringEncoding];
murequest.HTTPBody = param_data;
If we can’t get anything from that response, notice that the response serializer is correct. Any additional settings, please deal it with server.

Related

NSMutableURLRequest POST method with multiple objects

Below is my POST request example which saves Employee details. This work fine and I'm sending individual employee details.
But what if I have to save more then one Employee details...do I have to call below method those many time's ... How can I send all data in individual object like nsmutablearray of nsmutable dictionary....
-(void)saveEmployDetails
{
NSString * strBody = #"Employee=1&Class=tes&Comp=test&Type=Fixed";
NSString *strUrl = [[NSString alloc] initWithFormat:#"%#/api/external/SaveEmployee?type=%#", strCompURL, strType];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strUrl]];
request.HTTPMethod = #"POST";
request.HTTPBody = [strBody dataUsingEncoding:NSUTF8StringEncoding];
request.timeoutInterval = 5;
NSURLSessionDataTask *task = [sessionMnger dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200)
{
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:nil];
NSLog(#"data:%#", jsonData);
}
}
else
NSLog(#"Error:%#", error.description);
}];
[task resume];
}
Webservice Team gave me body for above API POST call like
This is a Post Method and below is the Body Object
[
{
"Employee":937,
"Class":test,
"Comp":test,
"Type":test
}
]
How to send more then one employee details together in above API
So the Webservice accepts json.
Just create an NSDictionary like this:
NSDictionary *emp = #{#"Employee":[NSNumber numberWithInt:1],
#"Class":#"Test",
#"Comp":#"Test",
#"Type":#"test"};
NSDictionary *emp1 = #{#"Employee":[NSNumber numberWithInt:1],
#"Class":#"Test2",
#"Comp":#"Test2",
#"Type":#"test2"};
NSArray *uploadArray = #[emp,emp1];
NSString *strUrl = [[NSString alloc] initWithFormat:#"%#/api/external/SaveEmployee?type=%#", strCompURL, strType];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strUrl]];
request.HTTPMethod = #"POST";
[request setHTTPBody:[NSJSONSerialization dataWithJSONObject:uploadArray options:NSJSONWritingPrettyPrinted error:nil]];
request.timeoutInterval = 5;
NSURLSessionDataTask *task = [sessionMnger dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
if (!error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if (httpResponse.statusCode == 200)
{
NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers|NSJSONReadingAllowFragments error:nil];
NSLog(#"data:%#", jsonData);
}
}
else
NSLog(#"Error:%#", error.description);
}];
[task resume];
Yes You can POST n number of employee details using your Web Service.
I think, you want to pass the NSArray inside the NSDictionary as a parameter along with the url to server.
Try like Hermann Klecker's answer and make changes accordingly:
[
{
"Employee":1,
"Class":"test 1",
"Comp":"test 1",
"Type":"test 1"
},
{
"Employee":2,
"Class":"test 2",
"Comp":"test 2",
"Type":"test 2"
}
]
Convert array into json string or make dictionary of post data than convert it into json string and post string to server.
Apparently you will have to form a body like this:
[
{
"Employee":1,
"Class":"test 1",
"Comp":"test 1",
"Type":"test 1"
},
{
"Employee":2,
"Class":"test 2",
"Comp":"test 2",
"Type":"test 2"
}
]
replace you string body
NSString * strBody = #"Employee = 1 & Class = tes & Comp = test & Type = Fixed"
to
NSString * strBody = #"Employee=1&Class=tes&Comp=test&Type=Fixed"

How to convert json format

How to remove \ and \n. This two is characters is coming.
{
PageNumber = 1;
businessCode = "{\n \"businessCode\" : \"[]\"\n}";
businessName = "";
categoryKeyword = "Ladies Traditional Wear Pagenumber";
languageCode = en;
location = "";
paginationSize = 5;
}
May be below answer is helpful for you.Follow this
//just give your URL instead of my URL
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"Your URL"]];
[request setHTTPMethod:#"GET"];
[request setValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"content-type"];
NSError *err;
NSURLResponse *response;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
//You need to check response.Once you get the response copy that and paste in ONLINE JSON VIEWER.If you do this clearly you can get the correct results.
//After that it depends upon the json format whether it is DICTIONARY or ARRAY
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:responseData options: NSJSONReadingMutableContainers error: &err];
From above code,you can get the correct format of JSON.Try this one.
NSMutableCharacterSet *charactersToRemove = [NSMutableCharacterSet new];
[charactersToRemove addCharactersInString:#"\n"];
[charactersToRemove addCharactersInString:#"\\"]; //This respresent obly one backslash, In Objective-c you have to support it with another slash
[jsonString stringByTrimmingCharactersInSet:charactersToRemove];

How to parse JSONP in Objective-C?

I am retrieving JSON information for an API and it says on the API that it is in JSON but I noticed it is in JSONP or "json with padding" as some call it. I tired to look everywhere to find how to parse this but no luck. The information I am trying to receive is this:
({"book":[{"book_name":"James","book_nr":"59","chapter_nr":"3","chapter":
{"16":{"verse_nr":"16","verse":"For where envying and strife is, there is confusion and
every evil work."}}}],"direction":"LTR","type":"verse"});
The link to the data is https://getbible.net/json?p=James3:16, so you can look at it directly.
This is the code I am using to try to retrieve the JSON Data and parse it into a NSMutableDictionary.
-(void)fetchJson {
NSString *currentURL = [NSString stringWithFormat:#"https://getbible.net/json?p=James"];
NSURL *url = [NSURL URLWithString:currentURL];
NSData *data = [[NSData alloc]initWithContentsOfURL:url];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
NSMutableData *receivedData = [[NSMutableData alloc] initWithLength:0];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self startImmediately:YES];
[receivedData setLength:0];
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:url MIMEType:#".json" expectedContentLength:-1 textEncodingName:nil];
expectedTotalSize = [response expectedContentLength];
if ([data length] !=0) {
NSLog(#"appendingData");
[receivedData appendData:data];
if(connection){
NSLog(#"Succeeded! Received %lu bytes of data",(unsigned long)[receivedData length]);
}
NSError *error;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
if(jsonResponse){
NSArray *responseArr = [jsonResponse mutableCopy];
NSLog(#"%lu",(unsigned long)[responseArr count]);
}else if (!jsonResponse){
//do internet connection error response
}
}
}
The results I am getting back from putting a breakpoint in the code is:
jsonResponse returns NULL
NSError NSCocoaErrorDomain code - 3840
but my NSData *data is returning 15640 bytes.
My console is displaying this from the NSLogs I used for debugging:
2014-04-20 01:27:31.877 appendingData
2014-04-20 01:27:31.879 Succeeded! Received 15640 bytes of data
I am receiving the data correctly but I am not parsing it correctly I know the error is because the JSON is in JSONP format. If anyone could please help with this I would appreciate it so much. I have tired to give as much detail on this question as I can but if you need more information just let me know so I can add it and make this as clear as possible.
Your code has at least two separate attempts to download the data. Neither is really correct. The code also only works with JSON, not JSONP.
Try this:
NSURL *url = [NSURL URLWithString:#"https://getbible.net/json?p=James"];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (data) {
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSRange range = [jsonString rangeOfString:#"("];
range.location++;
range.length = [jsonString length] - range.location - 2; // removes parens and trailing semicolon
jsonString = [jsonString substringWithRange:range];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *jsonError = nil;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonError];
if (jsonResponse) {
// process jsonResponse as needed
} else {
NSLog(#"Unable to parse JSON data: %#", jsonError);
}
} else {
NSLog(#"Error loading data: %#", error);
}
}];
One problem is that the data you're downloading has extraneous information at the beginning and end. The JSON being delivered by your URL is:
({"book":[{"book_name":"James","book_nr":"59","chapter_nr":"3","chapter":{"16":{"verse_nr":"16","verse":"For where envying and strife is, there is confusion and every evil work."}}}],"direction":"LTR","type":"verse"});
As the error message you're seeing indicates: you need to remove the initial ( from the beginning of the string and the ); from the end so that your JSON will start with the dictionary that your code expects. You can do this by calling subdataWithRange: on your NSData object:
NSData* jsonData = [data subdataWithRange:NSMakeRange(1, data.length-3)];
NSDictionary* jsonResponse = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:&error];
Just to update everyone, the NSURLRequest has been deprecated in iOS9. I tried the answer by #rmaddy, and I didn't receive anything either (just like what #lostAtSeaJoshua was encountering I guess). I have updated rmaddy's answer to reflect the NSURLSession implementation that has (I think) replaced NSURLRequest:
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:#"http://somerandomwebsite.com/get.php?anotherRandomParameter=5"];
[[session dataTaskWithURL:url
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// handle response
if (data) {
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"stringJSONed: %#",jsonString);
//Do something with the received jsonString, just like in # rmaddy's reply
} else {
NSLog(#"Error loading data: %#", error);
}
}] resume];
Just a heads up notice, when I first ran it, it gave me the security error. What you need to do (if you are using http) is to add this to your plist:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
I have to mention that after the NSAllowArbitraryLoads key, there are most probably other keys and values, such as NSExceptionDomain. But they're not really relevant to this answer I think. If you need to look further, let me know and I will dig deeper :)

simple mantle JSON example from URL

I have have some trouble in understanding what is needed to fetch a JSON file with mantle.h from a URL.
Can someone give me an example of how it works?
For example:
-I have a URL www.example.com with a JSONFile as follows:
{
"name": "michael"
}
How could I fetch it?
I use this process for fetching JSON:
NSURL *s = url;//Put your desird url here
NSURLRequest *requestURL = [NSURLRequest requestWithURL:s cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20.00];
NSHTTPURLResponse *response;
NSError *error = [[NSError alloc]init];
NSData *apiData = [NSURLConnection sendSynchronousRequest:requestURL returningResponse:&response error:&error];
dictionaryData = [NSJSONSerialization JSONObjectWithData:apiData options:kNilOptions error:&error];
Now the dictionaryData contains your JSON. You can fetch it by:
NSString *name = [dictionaryData valueForKey:#"name"];
And make sure you are making async request. For this put the code within this block:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
//Put the code here
});
Hope this helps.. :)
Call it with following method
[super getRequestDataWithURL:urlString
andRequestName:sometext];
You will get response in the following method if successful
- (void)successWithRequest:(AFHTTPRequestOperation *)operation withRespose:(id)responseObject withRequestName:(NSString *)requestName {
NSString *response = operation.responseString;
id jsonObject = [response objectFromJSONString];
if(![super checkforServerRequestFailureErrorMessage:jsonObject]) {
[self.leaderboardProxyDelegate leaderboardListSuccessful:jsonObject];
}
}
You will get dictionary in jsonObject

iOS: forcing server to provide updated data

I'm working on an iPad app that requests data from a server, changes and submits it, and then re-requests the data from the server, displaying it to the user. The app updates the data just fine (the equivalent web app sees the update happening), but the data that the iPad app gets back is the old data. I thought maybe it was the caching flag on the NSURLRequest, but it doesn't look like it.
Here is my sequence of calls:
NSString* currentStuff = self.fCurrentIndex.currentStuff;
NSError* err = nil;
[self.fCurrentIndex approve:currentStuff withUsername:username andPassword:password error:&err];
if (err == nil)
{
// rebuild the case list (grab the data from the URL again first)
[self getCaseListViaURL]; // grab the updated data
[self setupUIPanel]; // display it
}
Here's the code that grabs the data (the 'getCaseListViaURL' call):
NSURLResponse* response;
NSError* err = nil;
NSMutableDictionary * jsonObject = nil;
NSString * urlRequestString;
urlRequestString = [method to get the URL string];
NSURL * url = [NSURL URLWithString:urlRequestString];
NSURLRequest * request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
NSData * data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&err];
if (err == nil)
{
jsonObject = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&err];
}
if (err && error) {
*error = err;
}
return jsonObject;
Is there any way to force the server to serve up the updated data?
Thanks in advance.
EDIT: Per comments, I'm adding the sequence of update to the server and subsequent pull:
This does the push to the server:
NSString* currentStuff = self.fCurrentIndex.currentStuff;
NSError* err = nil;
[self.fCurrentPatient approveStuff:currentStuff withUsername:username andPassword:password error:&err];
Where 'approveStuff' eventually calls:
__block NSData * jsonData;
__autoreleasing NSError * localError = nil;
if (!error) {
error = &localError;
}
// Serialize the dictionary into JSON
jsonData = [NSJSONSerialization dataWithJSONObject:data
options:NSJSONWritingPrettyPrinted
error:error];
if (*error) return nil;
NSURLResponse* response;
NSString * urlRequestString;
urlRequestString = [self urlStringForRelativeURL:relativeURL
withQueryParams:params];
NSURL * url = [NSURL URLWithString:urlRequestString];
NSMutableURLRequest * request;
request = [NSMutableURLRequest requestWithURL:url
cachePolicy:self.cachePolicy
timeoutInterval:self.timeOutInterval];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:jsonData];
[request setValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
jsonData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&localError];
NSMutableDictionary * jsonObject;
if (localError == nil)
{
jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&localError];
}
if (error && localError) {
*error = localError;
}
return jsonObject;
Right after this, I call the aforementioned get call and rebuild the UI. Now, if I stick a breakpoint when I do the get, and check on the web server if the data is updated after the push, I see the data is there. However, when I let the get operation continue, it gives me the old data.
So it looks like the issue was on the server. There were some data structures on the server side that weren't being refreshed when the data was being posted.

Resources