Search code examples
asp.netobjective-cweb-servicesnsurlrequest

Special Characters in Webservice Request


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>&quot;Frank&quot;</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?


Solution

  • 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.