I'm sure I'm dense from being new to iOS programming, but, I am having problems with AFNetworking. Specifically, when I use it, nothing happens. I don't get any response from the server, but, I also don't get any errors. All of the properties end up NULL.
Here is my request:
NSMutableDictionary *requestArray = [NSMutableDictionary new];
[requestArray setObject: #"getBio"
forKey: #"action"];
[requestArray setObject: #"1"
forKey: #"bioID"];
NSError * error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:requestArray options:0 error:&error];
NSString *myRequestString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [ [ NSMutableURLRequest alloc ] initWithURL: [ NSURL URLWithString: #"http://localhost/LP/JSON/Secure/bio.php" ] ];
[ request setHTTPMethod: #"POST" ];
[ request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
[ request setHTTPBody: [myRequestString dataUsingEncoding:NSUTF8StringEncoding]];
This seems to work as I get my expected result if I simply pass the request into a UIWebView or if I use this:
NSURLResponse *response;
NSError *err;
NSData *returnData = [ NSURLConnection sendSynchronousRequest: request returningResponse:&response error:&err];
NSString *content = [NSString stringWithUTF8String:[returnData bytes]];
NSLog(#"responseData: %#", content);
In other words, the POST is successful and JSON is returned.
But, none of these do anything (no error, no response):
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Data: %# %#", [JSON valueForKeyPath:#"firstName"], [JSON valueForKeyPath:#"lastName"]);
} failure:nil];
Nor does even the bare bones attempt work:
AFURLConnectionOperation *operation = [[AFURLConnectionOperation alloc] initWithRequest:request];
Obviously, I'm doing something horribly wrong. But, the silent failures are making this hard to figure out.
Thanks for any help.
EDIT:
Nevermind.. I am dense.
Wasn't creating the NSOperationQueue.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
Although, I'm still unclear why the properties aren't getting set. But, it looks like I at least have data.
Creating the request operation object does not automatically kick off the request. Like you pointed out in your edit, it's up to you to either enqueue it into an NSOperationQueue or do [operation start] manually.
I would recommend that you communicate with your server using AFHTTPClient, since that provides a built-in mechanism to correctly set either your query string or HTTP body based on parameters you pass in. See the Gowalla API example client in the sample code, and the method AFHTTPClient -postPath:parameters:success:failure.
Related
I want to add my token in Authorization header
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSLog(#"%# urlis ====>",urlString);
NSData *data = [NSData dataWithContentsOfURL:url2];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *dataaa = [ret dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:dataaa options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
You can use NSMutableRequest -
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url2];
[request setHTTPMethod:#"GET"];
[request setValue:[[NSUserDefaults standardUserDefaults] valueForKey:#"token"] forHTTPHeaderField:#"Authorization"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// add any additional headers or parameters
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
// do your response handling
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
}
}];
[downloadTask resume];
To understand in more detail about NSURLSession refer to this Tutorial
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
[request addValue:VALUE forHTTPHeaderField:#"Authorization"];
Try to create a Mutable request and add your authorization header to it. You can send this request as a parameter to any one. Either to AFNetworking (or some third party network) library API calls or to URLSession (by Apple)
For more info on NSMutableRequest
You can pass it by
[request setValue:#"Your Token" forHTTPHeaderField:#"Authorization"];
Edited :
As per your comment if you want to change your response then your should use NSMutableDictionary instead of NSArray like.
Note: Your response should Dictionary if it will array then use NSMutableArray
NSMutableDictionary * resultDict =[json objectForKey:#"name"];
[resultDict setObject:#"Your Token" forKey:#"Authorization"];
I have been stuck for almost a week now, I want to write to a SharePoint list, usin the rest api they provide. The api looks like this, http://site/_api/lists, and from here I can read and write depending on what I append to my url, I can read from the lists without any issues, but I have issues when I have to write.
I am supposed to send in Content-Type, Accept, X-requestDigest headers, and post body when I write to list. My code
NSString *deviceToken = [self getDeviceTokenFromCoreData];
NSString *postData = [NSString stringWithFormat:#"{ \"__metadata\": { \"type\": \"SP.Data.TestListItem\" }, \"Title\": \"Test Title\" }"];
NSData *methodBodyData = [postData dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
NSData *jsonString = [NSJSONSerialization JSONObjectWithData:methodBodyData options:0 error:&error];
NSString *acceptType = #"application/json;data=verbose";
NSString *requestDigest = _requestDigest;
NSURL *subscribeURL = [[NSURL alloc] initWithString:subscribeUrlString];
NSMutableURLRequest *theRequest = [[NSMutableURLRequest alloc] initWithURL:subscribeURL];
[theRequest setHTTPMethod:#"POST"];
[theRequest setHTTPBody:jsonString];
[theRequest setValue:acceptType forHTTPHeaderField:#"Accept"];
[theRequest setValue:acceptType forHTTPHeaderField:#"Content-Type"];
[theRequest setValue:requestDigest forHTTPHeaderField:#"X-RequestDigest"];
This is where I construct my headers for the request. And this is how I handle the sending of the request
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:theRequest];
[operation setWillSendRequestForAuthenticationChallengeBlock:^(NSURLConnection *connection, NSURLAuthenticationChallenge *challenge) {
// if (challenge.previousFailureCount == 0) {
NSLog(#"%#", challenge.protectionSpace);
NSURLCredential *creds = [NSURLCredential credentialWithUser:userName
password:userPass
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:creds forAuthenticationChallenge:challenge];
} else {
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
}];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//Handle Success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//Handle failure
}];
[operation start];
}
This happens after I have authenticated to sharepoint, I have noticed during debugging the setWillSendRequestForAuthenticationChallengeBlock never gets called again, looks like I need to send the authentication information via the headers now, which is what I think the request digest is for, but that doesnt help cause I still don't get through.
Error message I get from server is
<?xml version="1.0" encoding="utf-8"?>
<m:error
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
<m:code>-2130575251, Microsoft.SharePoint.SPException</m:code>
<m:message xml:lang="en-US">The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again.</m:message>
</m:error>
Thanks in advance :)
I can't find any answer for this in internet. I solved in a non recommended way. I made a requisition using GET method to a page in the sharepoint application. In the return, i have a tag with the request digest value.
I used this in this way, in my POST requisition:
[headers setValue:#"0x175481C0D6D79A7534A0992E528A5B7D36C80C41C01CBEE55EFB256FA99E1EF551F755BAAE07E692ADE757290F1ACCA11B560F71338DE4AA7781ADC90CDC5249,11 Jun 2015 18:22:18 -0000" forKey:#"X-RequestDigest"];
I am super new to coding so there is most likely a better way but this is how I solved this issue:
Write a method that retrieves the Request Digest from the site that looks like this:
-(NSDictionary *)digestValue
{
NSURL *url = [NSURL URLWithString:#"https://.../sites/_api/contextinfo"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSArray* cookieArray = [NSArray arrayWithObjects: rtFaCookie, fedAuthCookie, nil];
NSDictionary * cookieHeaders = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieArray];
NSMutableDictionary * requestHeaders = [[NSMutableDictionary alloc] initWithDictionary: cookieHeaders];
[requestHeaders setObject: #"application/json;odata=nometadata" forKey: #"Accept"];
[requestHeaders setObject:#"application/json;odata=verbose" forKey:#"Content-Type"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:#"2" forHTTPHeaderField:#"Content-Length"];
[theRequest setAllHTTPHeaderFields:requestHeaders];
NSURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
if (data) {
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return [jsonString JSONValue];
}
return nil;
}
Then call that method when you need a valid Request Digest with something like this:
//Method Pulls the most current Digest Value from SharePoint, and pulls out just the Form Digest Value Key.
NSDictionary * taskMetas = [self digestValue];
NSString *formDigestValue = [taskMetas objectForKey:#"FormDigestValue"];
I am trying to call a web service that is developed with ASP.NET. The purpose is to pass a username and password to the web service to simulate a log-in procedure.
In order to call the service i used the following method:
NSError *errorReturned = nil;
NSString *urlString = #"http:myDomain/myMethod?Operation=SignIn";
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod: #"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:#"test" forKey:#"userName"];
[dict setObject:#"test" forKey:#"passWord"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:kNilOptions error:&errorReturned];
[request setValue:[NSString stringWithFormat:#"%d", [jsonData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody: jsonData];
NSURLResponse *theResponse =[[NSURLResponse alloc]init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&errorReturned];
if (errorReturned)
{
NSLog(#"%#", errorReturned);
}
else
{
NSString *retVal = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", retVal);
}
After running the app and clicking on the UIButton that fires the above method, nothing is shown in the console window.
The service returns the response in JSON format.
I want to know if i am missing something here since i am neither getting an error nor success log?
Any help would be appreciated!
Thank you.
Granit
A couple of thoughts:
If this method is getting called, you'd see something, even if retVal was empty and your
NSLog(#"%#", retVal);
just logged the app name and timestamp. Maybe change that NSLog to
NSLog(#"retVal = %#", retVal);
to remove any ambiguity. Or put in breakpoints in your code and single step through it to see what path the app takes.
Are you confident of your server interface? For example, is it possible that the Operation value of SignIn belongs in the JSON request, itself? Also, some services are case sensitive, so you might want to check that, too.
I don't know what access you have to the server, but it would be worthwhile to check the logs to make sure the request was received, possibly temporarily adding some logging within the code so you can confirm that the parameters were all received properly. Or, if nothing else, make sure that the server properly logs/reports any errors.
BTW, your instantiation of theResponse is unnecessary, and should just be
NSURLResponse *theResponse = nil;
The sendSynchronousRequest call doesn't populate an existing NSURLResponse instance, but rather creates a new instance and updates theResponse to point to it.
You should fix your request first, but you probably want, at the very least, to change this to use sendAsynchronousRequest instead of sendSynchronousRequest. You should never do synchronous calls on the main thread.
I solved my issue by using ASIHHTPRequest. Also i checked the server interface and it turned out that the parameters had to be sent with the URL.
-(void)signInAction:(id)sender{
NSURL *url = [NSURL URLWithString:#"http://mydomaain.com/UserService/SignIn/test/test"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDidFinishSelector:#selector(requestCompleted:)];
[request setDidFailSelector:#selector(requestError:)];
[request setDelegate:self];
[request setRequestMethod:#"GET"];
[request startAsynchronous];
}
- (void)requestCompleted:(ASIHTTPRequest *)request
{
NSString *responseString = [request responseString];
//[responseString UTF8String];
NSLog(#"ResponseString:%s",[responseString UTF8String]);
}
- (void)requestError:(ASIHTTPRequest *)request
{
NSError *error = [request error];
NSLog(#"Error:%#",[error description]);
}
I implement the JSON Parsing as follow:
-(void)getallEvent
{
SBJSON *json = [SBJSON new];
json.humanReadable = YES;
responseData = [[NSMutableData data] retain];
NSString *service = #"/GetAllVenue";
NSString *str;
str = #"Calagary";
NSString *requestString = [NSString stringWithFormat:#"{\"CityName\":\"%#\"}",str];
//NSLog(#"request string:%#",requestString);
// NSString *requestString = [NSString stringWithFormat:#"{\"GetAllEventsDetails\":\"%#\"}",service];
NSData *requestData = [NSData dataWithBytes: [requestString UTF8String] length: [requestString length]];
NSString *fileLoc = [[NSBundle mainBundle] pathForResource:#"URLName" ofType:#"plist"];
NSDictionary *fileContents = [[NSDictionary alloc] initWithContentsOfFile:fileLoc];
NSString *urlLoc = [fileContents objectForKey:#"URL"];
urlLoc = [urlLoc stringByAppendingString:service];
//NSLog(#"URL : %#",urlLoc);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: urlLoc]];
NSString *postLength = [NSString stringWithFormat:#"%d", [requestData length]];
[request setHTTPMethod: #"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: requestData];
// self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
NSError *respError = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: &respError ];
if (respError)
{
NSString *msg = [NSString stringWithFormat:#"Connection failed! Error - %# %#",
[respError localizedDescription],
[[respError userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Check your network connection" message:msg delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
else
{
NSString *responseString = [[NSString alloc] initWithData:returnData encoding: NSUTF8StringEncoding];
NSDictionary *results = [[responseString JSONValue] retain];
//NSLog(#" %#",results);
NSString *extractUsers = [[results objectForKey:#"d"] retain];
NSDictionary *finalResult = [[extractUsers JSONValue] retain];
NSLog(#"Final Results : %#",finalResult);
listOfEvents = [finalResult objectForKey:#"List of Event details of given Venue"];
}
Using this code, it slow down the app. How can I parse the json in background?
*Is this right for Post Method? what is the difference between Post & Get Method?*
Is there any other way to json parsing?
You are using synchronous request which is executed on Main thread so if you need to do it in background use asynchronous loading.
POST METHOD:
The POST method generates a FORM collection, which is sent as a HTTP request body. All the values typed in the form will be stored in the FORM collection.
GET METHOD: The GET method sends information by appending it to the URL (with a question mark) and stored as A Querystring collection. The Querystring collection is passed to the server as name/value pair. The length of the URL should be less than 255 characters.
An HTTP GET is a request from the client to the server, asking for a resource.
An HTTP POST is an upload of data (form information, image data, whatever) from the client to the server.
Check this answer for more details : what-is-the-difference-between-post-and-get
You are making synchronous communication request which slows down the application. You should make the asynchronous request to keep your app responsive.
It is not having any concern with parsing JSON data.
I would recommend using AFNetworking in your context which will simplify the connection management, background queue execution and parsing of the JSON you are getting back form the server.
The code example below will create an HTTP client with a base URL (<hostname>) and get a JSON payload from a given path. The network request runs in the background and runs a given block when completing
httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
// set the type to JSON
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
[httpClient setParameterEncoding:AFJSONParameterEncoding];
// Activate newtork indicator
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
// Request the <path> from the server and parse the response to JSON
// this calls a GET method to <hostname>/<path>
[httpClient getPath:<your path> parameters:Nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
// responseObject is a JSON object here
//
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// handle error
}];
Get: With the get method the value is send through the query string appended with the url. So you can see the the name, value, description on the addressbar when the page display in the browser.
Post: This method transfer the information through the complete form. You can not see the detail description on the addresss bar. When the page display.
NSString *myUrlString =[NSString stringWithFormat: #"your url];
NSString *postdata=[NSString stringWithFormat:#"emailId=%#&password=%#,username,password];
NSLog(#"%#",postdata);
//create a NSURL object from the string data
NSURL *myUrl = [NSURL URLWithString:myUrlString];
//create a mutable HTTP request
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:myUrl];
//sets the receiver’s timeout interval, in seconds
[urlRequest setTimeoutInterval:30.0f];
//sets the receiver’s HTTP request method
[urlRequest setHTTPMethod:#"POST"];
//sets the request body of the receiver to the specified data.
[urlRequest setHTTPBody:[postdata dataUsingEncoding:NSUTF8StringEncoding]];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//Loads the data for a URL request and executes a handler block on an
//operation queue when the request completes or fails.
[NSURLConnection
sendAsynchronousRequest:urlRequest
queue:queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 && error == nil){
//process the JSON response
//use the main queue so that we can interact with the screen
dispatch_sync(dispatch_get_main_queue(), ^{
[self parseResponse:data];
});
}
else if ([data length] == 0 && error == nil){
NSLog(#"Empty Response, not sure why?");
}
else if (error != nil){
NSLog(#"Not again, what is the error = %#", error);
}
}];
}
- (void) parseResponse:(NSData *) data
{
responseData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"JSON = %#", responseData);
NSLog(#"Response ==> %#", responseData;
Finally u get the response from that specific url .and what ever u wanted to it do ur own way.
I'm trying to make a POST request using NSURLConnection. I use Charles to debug and Charles every time says that the method is GET. I've tried all different ways and can't get it to work. I am NOT using JSON.
-(void)getList
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://example.com/api/getList"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *radius = #"15";
NSString *latitude = #"-117.820833";
NSString *longitude = #"34.001667";
NSString *parameters = [NSString stringWithFormat:#"longitude=%#&latitude=%#&radius=%#", longitude,latitude, radius];
NSLog(#"PARAMS = %#", parameters);
NSData *data = [parameters dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/plain" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:data];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *responseString = [[NSString alloc]initWithData:result encoding:NSUTF8StringEncoding];
NSLog(#"RESULT = %#", responseString);
}
Does anybody know what am I doing wrong? When I access my web service it seems like I'm not posting anything. I'm getting empty response.
Please help with any ideas. I pretty much have to make a simple POST request. Maybe someone can help me debug this better.
If the server is redirecting your request for some reason (perhaps authentication) then the POST information can get lost.