In the past I've been using the following code to send data from my app to a webservice that saves the data on my company's server (the webservice is written in asp.net).
- (NSArray *) callWebserviceWithPost:(NSString *)post andWithParser:(MyNSXMLParserDelegateClass *)parser
{
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"http://www.example.com/mywebservices/mywebservice.aspx"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
[request setTimeoutInterval:600];
NSHTTPURLResponse *response = nil;
NSError *err = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
if (!responseData)
{
NSString *msg = [NSString stringWithFormat:@"Response not recieved from web service"];
[Globals throwError:msg withCode:20 inMethod:_cmd onClass:[self class]];
return [NSArray arrayWithObject:errorString];
}
else
{
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
if ([[responseString substringToIndex:1] isEqualToString:@"<"])
{
// Create and init NSXMLParser object from data return by web service
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:responseData];
[nsXmlParser setDelegate:parser];
BOOL success = [nsXmlParser parse];
if (success)
{
return parser.allItems;
}
}
}
}
Where post would look something like
NSString *post = @"NewUser=<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<data>
<username>GeneralMike</username>
<status>Awesome</status>
</data>
</xml>"
This has worked fine for everything I've needed to do so far.
However, now I need to send some special characters in my data
...<username>"Frank"</username>...
I've done some research and discovered I can escape the special characters with certain codes. So this example would become
...<username>"Frank"</username>...
When I debug my webservice project with the post with the escapes added, it works fine. However, when I try to call the webservice from my app, I'm getting error messages in my response saying
Unexpected end of file has occurred. The following elements are not closed: username,data. Line 1, position ....
Counting over with the position provided, I've discovered this error is being thrown right where the &
is in the first escape.
I've also found a lot of stuff suggesting I need to use stringByAddingPercentEscapesUsingEncoding
or CFURLCreateStringByAddingPercentEscapes()
, but every way I've tried to use them, the webservice can't recognize what the request is.
Why do the escapes I linked work fine when I put them directly into the webservice project, but get lost when I try to send them from my app? What do I need to change to get them to work?
Since I control the webservice and the platforms consuming it, I was able to develop my own convention to deal with special characters. I know that for the content I'm sending right now, it's very unlikely I'd ever have a value containing a double underscore, and underscores seem to be legal for everything I've seen so far, so I developed a system where I spell out a character and surround it with underscores. So I'd have something like
...<username>__QUOTE__Frank__QUOTE__</username>...
in my new system. I can look for special characters just before sending a request from my app or a response from the webservice, and do the simple string replacements. Then as soon as I receive the XML, look for the replacements, and turn them back into the special characters before using the data (such as showing on a screen or saving into a database).
I don't particularly like this solution. I would much rather subscribe to a more universal convention. Since I can't seem to find that convention, if such convention exists, this will do for now.