Following problem:
I get every time the error -1000, but really don't know what I can change. I've tried it with GET and another sending method. But I get every time the same error.
Does someone see my mistake?
thanks
NSString *get =[[NSString alloc] initWithFormat:#"mobileNumber=%#&deviceToken=%#",myMobileNumber,myDeviceToken];
[get stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"http://myHomepage.net/login.php?%#",get]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *response = nil;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *responseData = #"";
if ([response statusCode] ==200 )
{
responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"---------responseData: %#",responseData);
return responseData;
} else {
You're not saving the result of stringByAddingPercentEscapesUsingEncoding. So, instead of:
[get stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
You need:
get = [get stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
FYI, while the above fix will now successfully percent escape all characters not permitted within in a URL, there are actually some characters that are acceptable in a URL, but are not acceptable within a parameter value (e.g. a + which is interpreted as a space, or & which delineates parameters).
It is important to percent escape the values used in the parameters of the request in such a way that you escape not only those characters that are not legal in a URL, but also a few that are otherwise legal in a URL, but are not permitted within a parameter value.
Unfortunately the standard stringByAddingPercentEscapesUsingEncoding method does not do this. But the CFURL function CFURLCreateStringByAddingPercentEscapes does. You apply this function to the individual parameter values. Here is a method that performs the necessary toll-free bridging between this function and ARC:
- (NSString *)percentEscapeString:(NSString *)string
{
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)string,
(CFStringRef)#" ",
(CFStringRef)#":/?#!$&'()*+,;=",
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
You can use this method as follows:
NSString *get =[[NSString alloc] initWithFormat:#"mobileNumber=%#&deviceToken=%#", [self percentEscapeString:myMobileNumber], [self percentEscapeString:myDeviceToken]];
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"http://myHomepage.net/login.php?%#",get]];
This should correctly percent escape the parameter values of the string, regardless of the presence of these reserved characters, or not.
Related
i start developing in iOS and i have the next problem:
i need to extract the page source of web page to extract some data from it.
with some urls i'v succseed and some not
here is my code that i get the page source:
(NSString *)getStringFromUrl:(NSString *)url{
NSError *err = nil;
NSString *agentString = #"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_6; en-us) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/3.2.1 Safari/525.27.1";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:url]];
[request setValue:agentString forHTTPHeaderField:#"User-Agent"];
NSData *data = [ NSURLConnection sendSynchronousRequest:request returningResponse: nil error: &err ];
NSString *returnData = [[NSString alloc] initWithBytes: [data bytes] length:[data length] encoding: NSUTF8StringEncoding];
if (err!=nil)
NSLog(#"error message: %#",err.description);
return returnData;
}
link that worked for me:
http://50.22.211.228:8000/played.html
link that not worked for me and return nil in returnData:
http://107.150.5.94:7070/played.html
The issue appears to be that the second request is apparently not returning valid NSUTF8StringEncoding. If you look at the NSData itself (if you log that, you'll see the hexadecimal representation of the binary payload), you are receiving data, but it's the conversion to a NSString that is failing.
If you look at that page in a web browser, it gets confused, too (the characters don't make sense). I'd wager that they are not writing a valid UTF8 string in that HTML, though it's not immediately obvious what precisely they're doing (it doesn't appear to be a string encoding that I recognize).
You can use NSASCIIStringEncoding to see the same mess in your code that you'll see in your web browser.
I use the following to get the source code of a web page as NSString:
NSError *error = nil;
NSString *urlString = [NSString stringWithFormat:#"%#", #"http://www.google.es"];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
NSString *webSource = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
I hope this helps you and is what you are looking for.
I want to program a NSXMLParser and I have the data for this lying in a NSString (encoded).
If I put the NSString to NSLog it gives me the right lines I need. But when I want to start the Parser with the data from that NSString it doesn't start.
Here is my code:
The interface:
#interface StundenplanParser () <NSXMLParserDelegate>
#end
The method that gets called from the ViewController:
-(void)parserStart
{
// Create your request string with parameter name as defined in PHP file
NSString *myRequestString = [NSString stringWithFormat:#"matr=%#&pressme=%#",#"33886",#"S T A R T"];
// Create Data from request
NSData *myRequestData = [NSData dataWithBytes: [myRequestString UTF8String] length: [myRequestString length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: #"http://www2.htw-dresden.de/~rawa/cgi-bin/auf/raiplan_app.php"]];
// set Request Type
[request setHTTPMethod: #"POST"];
// Set content-type
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
// Set Request Body
[request setHTTPBody: myRequestData];
// Now send a request and get Response
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil];
// Log Response
NSString *response = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSASCIIStringEncoding];
NSLog(#"Response:%#\n",[response substringToIndex:64]);
// If I would use NSASCIIStringEncoding in the following line, the data would be nil
NSData *data = [response dataUsingEncoding:NSUTF8StringEncoding];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
if (!parser) NSLog(#"Error with parser");
else NSLog(#"parser successfully initialised");
[parser setDelegate:self];
[parser parse];
}
NOTE: In my response (NSString*) is the code that I want to parse. If I print it out using NSLog I see the source code of the website..
Now I want to show only the elements the NSXMLParser found with this:
-(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
NSLog(#"found element: %#", elementName);
}
I hope it's not a problem that I left the url in the code. I just want to parse the schedule from my university.
I hope you understand what I mean and you could help me.
EDIT: My Problem is not that I don't get the XML. My Problem is that the parser won't start.. I edited the code.
EDIT2: The output from the response is:
2013-11-18 23:52:16.008 University[17210:70b] Response:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN
So it seems like it worked, but the problem is the encoding of this into a NSData instance that I need to initialize my parser.
EDIT3:
After implementing the parser:parseErrorOccurred I got the following error in the Console:
2013-11-19 08:58:26.190 University[17458:70b] ERROR while parsing: The operation couldn’t be completed. (NSXMLParserErrorDomain error 65.)
Translating with Google, the website
http://www2.htw-dresden.de/~rawa/cgi-bin/auf/raiplan_app.php
says 'Create a schedule in csv format' and entering the matriculation number from your code 33886, it returns a web page that has in its the data you're trying to get at:
<Stunde>
<titel>Englisch C1 III/SI (w.o.)</titel>
<kuerzel>Engl_C1 Üw3/SI Technik</kuerzel>
<raum>S 334</raum>
<dozent>Kilian</dozent>
<datum>16.10.2013</datum>
<anfang>7:30</anfang>
<ende>9:00</ende>
</Stunde>
If you extract this data and form a new XML string, then the XML Parser will run. The tag is where this data begins, and the last one is followed by a , so this code will extract out the elements:
NSRange startRange = [dataString rangeOfString:#"<Stunde>"];
NSString *dataAfterHtml = [dataString substringFromIndex:startRange.location];
NSRange endRange = [dataAfterHtml rangeOfString:#"<br>"];
dataAfterHtml = [dataAfterHtml substringToIndex:endRange.location];
NSString *formattedXML = [NSString
stringWithFormat:#"<data>%#</data>",
dataAfterHtml];
now give this the parser
NSData *data = [formattedXML dataUsingEncoding:NSUTF8StringEncoding];
xmlParser = [[NSXMLParser alloc] initWithData:data];
You are interpreting the data as ASCII and then encoding it as UTF8, you are going to end up with an invalid string or with a string with invalid characters. Try this:
...
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:returnData];
[parser setDelegate:self];
[parser parse];
You problem is that you are not URLEncoding the data, but feeding it draw into the HTTP body. In this:
NSMutableData *body = [NSMutableData data];
NSString *postWerte = #"matr=XXXXX&lang=1&aktkw=1&pressme=S T A R T";
[body appendData:[postWerte dataUsingEncoding:NSUTF8StringEncoding]];
you need to URLEncode "S T A R T", and should bee really URLencoding every string that follows an equal sign. (UPDATE: so it works as is - my service is way picker and I must encode. YMMV!)
EDIT:
So try changing your code a bit, and if it still fails then please post the first line or two of the returned data:
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil];
assert(returnData); // you should be suppling an error pointer just in case but this will do for now
// Log Response
{
NSString *response = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSASCIIStringEncoding];
NSLog(#"%#",[response substringToIndex:64]); // or a bit mor
}
NSXMLParser *parser = [[NSXMLParser alloc] initWithData: returnData];
assert(parser); // will be nil if anything has gone wrong, obviously in your real code put an if test
[parser setDelegate:self]; // no affect for nil object
[parser parse];// no affect for nil object
EDIT2:
BTW, I missed this, and it may not make a difference, but the parser object has no property "delegate", you technically should be using the setter:
[parser setDelegate:self];
Also, you did implement the following, right?
parserDidStartDocument: // which I assume you never see, right
parser:validationErrorOccurred:
parser:parseErrorOccurred:
parserDidEndDocument: // you never see this either?
If parser is nil, dump the whole returned data as a UTF8 string (per the log code). Also, try looking for an error:
dispatch_async(dispatch_get_main_queue(), ^
{
NSLog(#"PARSE ERROR: %#", [parser parseError]);
} );
I'm sending base64 string to php server and its working well. Now I want to send another parameter as a string. Can anyone tell me what code need to add in below code.
Below code is working good for single parameter. How can we modify it for multiple parameters?
NSData *data = [UIImageJPEGRepresentation(imgeview.image,90) base64Encoding];
// Create your request string with parameter name as defined in PHP file
NSString *myRequestString = [NSString stringWithFormat:#"question_image=%#",data];
myRequestString = [myRequestString stringByReplacingOccurrencesOfString:
#"+" withString:#"%2B"];
// Create Data from request
NSData *myRequestData = [NSData dataWithBytes:[myRequestString UTF8String]
length:[myRequestString length]];
request = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:#"http://192.168.0.101/Mobile_tutor/webservice/question_details.php"]];
// set Request Type
[request setHTTPMethod:#"POST"];
// Set content-type
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
// Set Request Body
[request setHTTPBody:myRequestData];
// Now send a request and get Response
NSData *returnData = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil
error: nil];
// Log Response
NSString *response = [[NSString alloc] initWithBytes:[returnData bytes]
length:[returnData length]
encoding:NSUTF8StringEncoding];
NSLog(#"-------------%#",response); // here you get reasponse string
For the network operation these is better supporting API like AFNetworking available witch work async and way better to handle
Tutorials for AFNetworking
Get from here
NSArray *keys = #[#"UserID", ];
NSArray *objects = #[#(userId)];
NSDictionary *parameter = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:
[NSURL URLWithString:BaseURLString]];
[httpClient setParameterEncoding:AFJSONParameterEncoding];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST"
path:#"services/UserService.svc/GetUserInfo"
parameters:parameter];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError* error = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&error];
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
// do what ever
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
Given a NSDictionary "params" whose keys and values are strings and where every entry represents one parameter (name/value) you can define a helper category:
#interface NSDictionary (FormURLEncoded)
-(NSData*) dataFormURLEncoded;
#end
dataFormURLEncoded returns a properly encoded character sequence from the given parameters in the dictionary.
The encoding algorithm is specified by w3c: URL-encoded form data / The application/x-www-form-urlencoded encoding algorithm
It can be implemented as follows:
First, a helper function which encodes a parameter name, respectively a parameter value:
static NSString* x_www_form_urlencoded_HTML5(NSString* s)
{
// http://www.w3.org/html/wg/drafts/html/CR/forms.html#application/x-www-form-urlencoded-encoding-algorithm , Editor's Draft 24 October 2013
CFStringRef charactersToLeaveUnescaped = CFSTR(" ");
CFStringRef legalURLCharactersToBeEscaped = CFSTR("!$&'()+,/:;=?#~");
NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
kCFAllocatorDefault,
(__bridge CFStringRef)s,
charactersToLeaveUnescaped,
legalURLCharactersToBeEscaped,
kCFStringEncodingUTF8));
return [result stringByReplacingOccurrencesOfString:#" " withString:#"+"];
}
Finally, dataFormURLEncoded composes the character sequence of the encoded parameters. A "parameter" will be composed by concatenating the encoded name, = and encoded value:
parameter := name "=" value
Then, the parameter list will be composed by concatenating the parameters by separating them by a "&":
parameters := parameter ["&" parameter]
It can be implemented as below:
#implementation NSDictionary (FormURLEncoded)
-(NSData*) dataFormURLEncoded {
NSMutableData* data = [[NSMutableData alloc] init];
BOOL first = YES;
for (NSString* name in self) {
#autoreleasepool {
if (!first) {
[data appendBytes:"&" length:1];
}
NSString* value = self[name];
NSData* encodedName = [x_www_form_urlencoded_HTML5(name) dataUsingEncoding:NSUTF8StringEncoding];
NSData* encodedValue = [x_www_form_urlencoded_HTML5(value) dataUsingEncoding:NSUTF8StringEncoding];
[data appendData:encodedName];
[data appendBytes:"=" length:1];
[data appendData:encodedValue];
first = NO;
}
}
return [data copy];
}
#end
Note: The character sequence encodes the strings using Unicode UTF-8.
Example:
Given your parameters:
NSDictionary* params = #{#"a": #"a a", #"b": #"b+b", #"c": #"ü ö"};
NSData* encodedParamData = [params dataFormURLEncoded];
Now, encodedParamData will be added to your body whose content type is application/x-www-form-urlencoded.
The encoded parameter string becomes:
a=a+a&b=b%2Bb&c=%C3%BC+%C3%B6
I use the following code to create a dictionary based on a JSON string received from the server. (I have downloaded JSONKit and embedded it into the project). The code below returns a legal JSON string from the server (parsed well on Android) but crashes when I try to convert it to a dictionary.
- (IBAction)submit
{
bool useSSL = true;
char *c_url="http://(rest of URL)";
NSString* url = [NSString stringWithFormat:#"%s" , c_url];
url = [NSString stringWithFormat:#"%#%#%s", url, self.label.text, "/keys"];
NSString * response = [self getDataFrom:url];
NSDictionary *dict = [response objectFromJSONString]; //generates SIGABRT!!
NSLog(#"%#",dict);
NSString *success = [dict valueForKey:#"success"];
}
- (NSString *) getDataFrom:(NSString *)url{
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setHTTPMethod:#"GET"];
[request setURL:[NSURL URLWithString:url]];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *responseCode = nil;
NSData *oResponseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&responseCode error:&error];
if([responseCode statusCode] != 200){
NSLog(#"Error getting %#, HTTP status code %i", url, [responseCode statusCode]);
return nil;
}
return [[NSString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
}
THANKS,
Simon
Found an answer here.
Answer says: "Figured it out... I had JSONKIt.h included in the project but for some weird reason, JSONKit.m was not included in the 'Compile Sources' under 'Build Phases' - once I added it manually it started working fine."
My App_Code/IGetEmployees.vb file
<ServiceContract()> _
Public Interface IGetEmployees
<OperationContract()> _
<WebInvoke(Method:="POST", ResponseFormat:=WebMessageFormat.Json, BodyStyle:=WebMessageBodyStyle.Wrapped, UriTemplate:="json/contactoptions")> _
Function GetAllContactsMethod(strCustomerID As String) As List(Of NContactNames)
End Interface
My App_Code/GetEmployees.vb file
<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function GetAllContactsMethod(strCustomerID As String) As List(Of NContactNames) Implements IGetEmployees.GetAllContactsMethod
Utilities.log("Hit get all contacts at 56")
Dim intCustomerID As Integer = Convert.ToInt32(strCustomerID)
Dim lstContactNames As New List(Of NContactNames)
'I add some contacts to the list.
Utilities.log("returning the lst count of " & lstContactNames.Count)
Return lstContactNames
End Function
NContactNames is a class with 3 properties.
So i am using ASP.NET web services to retrieve information from SQL server and pass it to my iPad in JSON format. I have a problem with parameter passing. So like you see i have 2 files IGetEmployees.vb and GetEmployees.vb. I am implementing the method GetAllContactsMethod. What's happening is the two lines in GetEmployees.vb file (Utilities.log), they never get logged. The function is not getting called at all.
My objective c code to call this function
NSString *param = [NSString stringWithFormat:#"strCustomerID=%#",strCustomerID];
jUrlString = [NSString stringWithFormat:#"%#",#"http://xyz-dev.com/GetEmployees.svc/json/contactoptions"];
jurl = [NSURL URLWithString:jUrlString];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:jurl];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[param dataUsingEncoding:NSUTF8StringEncoding]];
NSLog(#" request string is %#",[[request URL] absoluteString]);
NSLog(#"Done");
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
if(theConnection)
{
jData = [NSMutableData data];
NSError *jError;
NSMutableDictionary *json =[NSJSONSerialization JSONObjectWithData:jData options:kNilOptions error:&jError];
NSLog(#"%#",json); //Gets Here and prints (null)
NSLog(#"Done"); //prints this as well.
}
else
{
NSLog(#"No");
}
At the time of posting this code the "if" statement is true and (null) is printed followed by "Done"
The output of my absolute request is:
request string is http://xyz-dev.com/GetEmployees.svc/json/contactoptions
This is the first time i am writing json to accept parameters. So i might be missing something.What is it?Why is the function not getting called at all on the Visual Studio side. If you need more info please ask.Thanks...
this is the moethod in Objetive-C, for that.
-(void) insertEmployeeMethod
{
if(firstname.text.length && lastname.text.length && salary.text.length)
{
NSString *str = [BaseWcfUrl stringByAppendingFormat:#"InsertEmployee/%#/%#/%#",firstname.text,lastname.text,salary.text];
NSURL *WcfSeviceURL = [NSURL URLWithString:str];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:WcfSeviceURL];
[request setHTTPMethod:#"POST"];
// connect to the web
NSData *respData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// NSString *respStr = [[NSString alloc] initWithData:respData encoding:NSUTF8StringEncoding];
NSError *error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:respData
options:NSJSONReadingMutableContainers
error:&error];
NSNumber *isSuccessNumber = (NSNumber*)[json objectForKey:#"InsertEmployeeMethodResult"];
//create some label field to display status
status.text = (isSuccessNumber && [isSuccessNumber boolValue] == YES) ? [NSString stringWithFormat:#"Inserted %#, %#",firstname.text,lastname.text]:[NSString stringWithFormat:#"Failed to insert %#, %#",firstname.text,lastname.text];
}
}
Before to run the code, test your URL with POSTMAN, is an app from Google Chrome.
regards.