JSON Payload doesnt seem to be sending - objective-c

My problem I'm pretty positive is simple, I must just be missing something.. just not sure what.
I can send GET and POST for granular elements (this=that kind of stuff), but a web service call I need to send data too, takes a raw JSON block, with no "key"
Heres the method I wrote:
-(NSData *)execute {
// Smart Chooser ?
if(PostData.count >0 || Payload != nil)
[self setMethod:UPLINK_METHOD_POST];
else
[self setMethod:UPLINK_METHOD_GET];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.connectionUrl
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10];
if([UPLINK_METHOD_GET isEqualToString:self.connectionMethod])
[request setHTTPMethod:#"GET"];
else
[request setHTTPMethod:#"POST"];
NSString *gData = [self compileGetData];
NSString *pData = [self compilePostData];
// if we have get data, set it into the URL string
if(GetData.count > 0) {
[self setURLWithString:[[self.connectionUrl absoluteString] stringByAppendingString:[#"?" stringByAppendingString:gData]]];
[request setURL:self.connectionUrl];
}
// if we have post data, set it in the body
if(PostData.count > 0) {
const char *bytes = [[NSString stringWithString:pData] UTF8String];
[request setHTTPBody:[NSData dataWithBytes:bytes length:strlen(bytes)]];
}
// Override any post data if a payload is already defined.
if(Payload != nil) {
[request setHTTPBody:[Payload dataUsingEncoding:NSUTF8StringEncoding]];
}
NSLog(#"URL : %#", request.URL);
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
if(err != nil)
NSLog(#"here was an error: %#", err);
return responseData;
}
-(NSDictionary *)executeAsJSON
{
NSData *responseData = [self execute];
NSError *e;
return [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];
}
Ok SO, the way this thing works, is that it automatically sets whether the request is POST or GET depending on the data provided in the GetData, PostData, and Payload vars.
The request is GET by default, but turns into POST if PostData or Payload have anything in them.
The compileGetData and compilePostData mostly just bring back formatted strings with arrays of information combined, nothing special there.
But thats not where the problem is.
See, "Payload" overrides anything "PostData" had in it. If you had provided PostData elements into the class, it would just be overridden by a provided Payload if that does exist.
I needed to provide this to demonstrate the "workarea" as it exists right now, its not linearly provided information.
This is the area of interest:
// Override any post data if a payload is already defined.
if(Payload != nil) {
//const char *plbytes = [[NSString stringWithString:Payload] UTF8String]; // this didn't work
[request setHTTPBody:[Payload dataUsingEncoding:NSUTF8StringEncoding]]; // inline, doesn't work either
}
When I say "doesnt work", what I mean is, im getting back an error JSON array from the webservice that basically means "hey, wheres the payload?". If the request is not POST it comes back as a general error, so thats all working, the URL is then obviously correct.
I've used RESTConsole for Chrome to test the webservice to make sure its working properly, and it does.
I've also checked through the debugger the exact payload im sending, i copy+pasted that into RESTConsole, and it works there.
I'm.. honestly at a loss here...

Try using a web proxy like Charles or Wireshark (I personally preferr Charles due to it's ease of use, it's a 30-day trial though) and monitor the request you make from RESTConsole and the one you make from your app and see if they look the same.
Check any headers, line returns and anything else that looks different.
That's the best I can think of to start with

Related

URL reachablility - false positive

There are a ton of "false positive" posts, though none appear to match my situation. (Most are talking about internet connection errors..)
As with everyone almost else, I just want to determine whether a specific URL is valid.
Now, I'm dealing with subdomains, and it works great as long as I choose a valid domain. If I choose an invalid subdomain, I get a false positive. Using a browser to test reveals that my ISP gives me a really annoying suggestions page if I type in a URL that doesn't exist.
Any way to validate that the responding server IS actually at the URL I asked for?
My Code:
-(BOOL) canConnectToURL:(NSString * )sURL {
BOOL bSuccess = NO;
if (![txtSubDomain.text.lowercaseString isEqual: #"www"]){
NSLog(#"canConnectToURL(%#)",sURL);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: sURL]];
[request setHTTPMethod: #"HEAD"];
NSURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest: request returningResponse: &response error: &error];
NSLog(#"URL: %#",sURL);
NSLog(#"data: %#",response);
bSuccess = ([(NSHTTPURLResponse *)response statusCode] == 200);
}
return bSuccess;
}
I believe you can attach a delegate to your NSURLRequest that handles the method connection:willSendRequest:redirectResponse: in the NSURLConnectionDataDelegate protocol, and catch it there.
https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSURLConnectionDataDelegate_protocol/Reference/Reference.html#//apple_ref/doc/uid/TP40011348-CH1-SW9

JSON Parsing Error in ios

I want to fetch some data from some url and print result in nslog.
I am passing URl and want to fetch result in log only.
I have used this code :
-(void)GETJSONDATA
{
NSString*lu=#"tmp";
NSString *requestString = [[NSString alloc]init];
// [[NSUserDefaults standardUserDefaults] setValue:nil forKey:#"WRONGANSWER"];
NSLog(#"request string:%#",requestString);
NSData *requestData = [NSData dataWithBytes: [requestString UTF8String] length: [requestString length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString: #"http://assessments.tlisc.org.au/webservices/questions/getbytaskpart.php?jsoncallback=?&token=1726204214321678|xTAieBBJoDaWmBsG1stxfq4zLO4&taskpartid=1"]];
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];
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:#"Test" message:#"check your network connection" delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alertView show];
}
else
{
NSString *responseString = [[NSString alloc] initWithData:returnData encoding: NSUTF8StringEncoding];
NSLog(#"Resp : %#",responseString);
NSDictionary *results = [responseString JSONValue];
NSLog(#"results=%#",results);
}
}
It is showing me this error :
-JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=11 \"Unexpected end of string\" UserInfo=0x6a42be0 {NSLocalizedDescription=Unexpected end of string}"
Can anybody point me error?
In response string , it is showing null value.
I don't know the actual error.
it is working fine in browser but when I parse it it is showing this error....Is there anyway through which I can modify the url and get result ...i have checked my code with different url.and it is working proper..
I think I was using the same library as you're using here, and for some unexplained reason it just failed on a particular google api, sometimes getting results but usually failing. There appeared to be nothing wrong with the code.
In the end I went with the inbuilt NSJSONSerialization ( http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSJSONSerialization_Class/Reference/Reference.html ) object and it hasn't failed since. I wasn't even aware there was JSON support built in (from iOS5 apparently).
I ran the two calls and processed them side by side, the external library continually failed. The internal methods worked fine.
Since I'm a beginner and the docs (above) don't really help me a lot, I used this tutorial http://www.raywenderlich.com/5492/working-with-json-in-ios-5 to get my head around it
As the error told you: the incoming JSON is not well-formed. Making a simple GET request to the URL you are using, I'm getting a JSON that is malformed, i.e. it is not valid JSON. I guess posting data to this URL returns the same format with actual data in it (not null).
Making use of a simple JSON Validator, I'm getting this
Parse error on line 5: ... "Description": "\n\tQuestion Numbe
-----------------------^ Expecting 'STRING', 'NUMBER', 'NULL', 'TRUE', 'FALSE', '{', '['
Check your url in a browser. See the result. Your result's Structure should be like the same as JSON. if there is any other extra word in start of the json means. you should check your php code.
You have got HTML tags within your strings. Paragraph marks like
<p> and </p>
And these are not properly escaped. However, I do not know by hard wether the less than sign and greater than sign need to be escaped in JSON but apparently they are creating the issue.
Using google I find statements for both. However, some site suggests escaping < with \u003c and > with \u003e. that should do the trick.
I tried to validate the output from
http://assessments.tlisc.org.au/webservices/questions/getbytaskpart.php?jsoncallback=?&token=1726204214321678|xTAieBBJoDaWmBsG1stxfq4zLO4&taskpartid=1
It seems to be valid though if the <p> and </p> ist not interpreted by the bowser. (I was lookint to the "page source").
However, when escaped the string is still valid and encodes to the same result.
If this is not your issue, then please provide the output of your
NSLog(#"Resp : %#",responseString);

JSON broken in Objective-C URL Request

After pounding my head all day long, I am down to StackOverflow to pull me through.
I am making a NSURLRequest in my iPhone App ...
NSURL* url = [[self serviceUrl] URLByAppendingPathComponent:[NSString stringWithFormat:#"Json"]];
NSString* json = [NSString stringWithFormat:#"{\"id\":\"%#\"}", id];
NSMutableURLRequest* urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[urlRequest setHTTPBody:[json dataUsingEncoding:NSUTF8StringEncoding]];
this is returning to me a JSON string, which comes back to me but it is broken in the since that the string will not parse correctly.
However if I make a normal request to the same url in the Safari browser then JSON is returned correctly. I am validating this JSON here.
So whats the deal? Is there a limit to the length of data in a NSString* that a 32Kb json file would not be stored in memory correctly? Sometimes the JSON can be parsed, which leads me to believe that I am not clearing my JSON string correctly after each request.
_json = [[NSString alloc] initWithData:_dataResponse encoding:NSUTF8StringEncoding];
NSArray* retrievedData = (NSArray*)[_json JSONValue];
// removed for brevity
_json = #"";
Other information, I am using ASP.NET MVC 3 to provide the web services for this app.
EDIT
- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
{
_loader.hidden = NO;
[_loadingIndicator startAnimating];
return request;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
_dataResponse = [[NSMutableData alloc] init];
[_dataResponse setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_dataResponse appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Error receiving response: %#", error);
_loader.hidden = YES;
[_loadingIndicator stopAnimating];
}
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
_json = [[NSString alloc] initWithData:_dataResponse encoding:NSUTF8StringEncoding];
// Removed for brevity
_json = #"";
_loader.hidden = YES;
[_dataResponse release];
_dataResponse = nil;
[_loadingIndicator stopAnimating];
}
FINAL SOLUTION
I was making multiple calls to have data already stored for views in order to switch views in a tab bar controller. I wasn't checking the connection during the appending of the data, I was checking the connection when it was finished in order to store the data correctly. My final solution was to make each call sychronously after the previous one during the finished method call.
Unfortunately, nothing blatant is jumping out at me.
Some things to try that will hopefully help:
double check your NSUrlConnection pattern against this doc. The only diff I see is they're doing [[NSMutableData data] retain] instead of alloc, init. They also create NSMutableData with the connection request (not in response) and only length=0 in response. Not sure why it would matter though ...
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html
try something like Charles Proxy. It allows you to sniff the wire. You can see what's different between browser and simulator/phone access. At a minimum, you'll see what's coming over the wire in the bad cases.
add lots of logging. everytime you append data, log some details. After you convert to string and before the json call, log. Log sizes, etc... Something may offer you a hint.
the use of _json string seems a bit off. You're reallocating and then setting to empty string. You should either have an iVar that you alloc and release (not set to "") or create a #property with retain, copy.
You should definitely include charset=utf8 in you content-type header. And how do you know that the response you get is encoded as utf8? You should also set content-size header.

ASIFormDataRequest - iOS Application. How do I RETRIEVE a post variable

So I have this url that leads to a .php
So far I managed to retrieve every single thing except the actual XML that I want. the XML is stored in a variable called _xml.
if($this->outMethod=="" || $this->outMethod=="POST") //Default to POST
{
$_POST["_xml"] = $_xml;
}
So I've already set the outMethod to POST but I don't understand how to retrieve the value within _xml.
- (void)grabURLInBackground
{
NSLog(#"grab url in background");
NSURL *url = [NSURL URLWithString:#"xxxxxxxxxxx"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"POST" forKey:#"outMethod"];
[request setPostValue:#"1" forKey:#"Entity_ID"];
[request setDelegate:self];
[request startAsynchronous];
NSLog(#"end of grabUrlInBackgroun");
}
don't worry the URL is right I just don't want to post it.
- (void)requestFinished:(ASIHTTPRequest *)request
{
NSLog(#"A");
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
if(responseString)
{
NSLog(#"responseData is not null");
}
NSLog(#"response string: %#", responseString);
//NSLog(#"%#", responseString);
}
What I get back is that the request is good, but there is no response in responseString. This is because my php does not want to print out any of the XML on screen in HTML but it stores the result in the variable _xml sent via post "$_POST["_xml"] = $_xml
My question is, how do I get back that xml variable? Isn't there a method available within the ASIHTTPRequest library? I am using ASIFormDataRequest class not ASIHTTPRequest.
You have to print you variable in the php-file:
if($this->outMethod=="" || $this->outMethod=="POST") //Default to POST
{
echo $_xml;
}
A HTTPRequest (and the ASIFormDataRequest as well) isn't interested in any variables you declare in your *.php file. It only returns the string you actually print.

Xcode: Validate a URL before Loading it

Im having some trouble findig a way to validate a url on my app.
My intention is to load a URL and at the same time see if other webpage exist for example.
Load http://mysite.com/folder1/1.pdf
validate http://mysite.com/folder1/2.pdf
if folder1/2.pdf exists then load it, else validate /folder2/1.pdf
so far im loading the first pdf like this in order to be able to change the pdf number and the folder:
int numpag = 1;
NSString *baseUrl =#"http://www.cronica.com.mx/iphone/pdf_iphone/";
[pdfView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[baseUrl stringByAppendingFormat:#"folder1/%d.pdf", numpag]]]];
Thanks so much in advance!
how about this:
+ (BOOL)isValidURL:(NSURL*)url
{
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSHTTPURLResponse *res = nil;
NSError *err = nil;
[NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&err];
return err!=nil && [res statusCode]!=404;
}
let me know if it works for you!
(keep in mind that this is a synchronous request and should not be executed on the main thread)
I had to change the line:
return err!=nil && [res statusCode]!=404;
to
return err==nil && [res statusCode]!=404;
for the correct Bool return. The error should remain nil.
This approach is NOT correct, You should avoid Synchronous calls as they are blocking.
Apple says: simply try and wait down to wait for response.