How do I send XML POST data from an iOS app to a Django app?
Question: I am attempting to implement an online leaderboard in a game app for iOS,
using Django to process POST requests from the iDevice and store the scores. I
have figured out how to get Django to serialize the objects to XML, and my
iPhone can read and display the scores. However, I can't for the life of me
get my iPhone to POST XML to my Django server.

Below is the function I am using to post the scores...

## iOS (Objective-C) Controller:

    
    
    - (void) submitHighScore {
        NSLog(@"Submitting high score...");
    
        NSString *urlString = HIGH_SCORES_URL;
        NSURL *url = [NSURL URLWithString: urlString];
    
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL: url];
        [request setHTTPMethod: @"POST"];
        [request setValue: @"text/xml" forHTTPHeaderField: @"Content-Type"];
    
        NSMutableData *highScoreData = [NSMutableData data];
        [highScoreData appendData: [[NSString stringWithFormat: @"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"] dataUsingEncoding: NSUTF8StringEncoding]];
        [highScoreData appendData: [[NSString stringWithFormat: @"<player_name>%@</player_name", @"test"] dataUsingEncoding: NSUTF8StringEncoding]];
        [highScoreData appendData: [[NSString stringWithFormat: @"<score>%d</score>", 0] dataUsingEncoding: NSUTF8StringEncoding]];
        [highScoreData appendData: [[NSString stringWithFormat: @"</xml>"] dataUsingEncoding: NSUTF8StringEncoding]];
        [request setHTTPBody: highScoreData];
    
        [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: YES];
    
        NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest: request 
                                                                      delegate: self];
        if (!connection) {
            NSLog(@"Request to send high scores appears to be invalid.");
            [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible: NO];
        }
    }
    

The above method succeeds in sending the request, and interprets it correctly
as `CONTENT_TYPE: text/xml`, but the Django view that processes the request
can't seem to make any sense of it, interpreting it almost as if it was merely
plain text. Below is my Django view...

## Django (Python) view:

    
    
    from django.http import HttpResponse, HttpResponseBadRequest
    from django.shortcuts import render_to_response
    from django.template import RequestContext
    from django.core import serializers
    from django.core.exceptions import ValidationError
    from django.views.decorators.csrf import csrf_exempt
    
    from modologger.taptap.models import HighScore
    
    @csrf_exempt
    def leaderboard( request, xml = False, template_name = 'apps/taptap/leaderboard.html' ):
        """Returns leaderboard."""
        if xml == True: # xml is set as True or False in the URLConf, based on the URL requested
            if request.method == 'POST':
                postdata = request.POST.copy()
                print postdata
                    # here, postdata is evaluated as: 
                    # <QueryDict: {u'<?xml version': [u'"1.0" encoding="UTF-8" ?><player_name>test</player_name<score>0</score></xml>']}>
                for deserialized_object in serializers.deserialize('xml', postdata):    # this fails, returning a 500 error
                    try:
                        deserialized_object.object.full_clean()
                    except ValidationError, e:
                        return HttpResponseBadRequest
                    deserialized_object.save()
            else:   
                high_score_data = serializers.serialize( 'xml', HighScore.objects.all() )
                return HttpResponse( high_score_data, mimetype = 'text/xml' )
        else:
            high_scores = HighScore.objects.all()
            return render_to_response( template_name, locals(), context_instance = RequestContext( request ) )
    

To be honest, I'm not sure whether the problem lies in the Objective-C or in
the Django code. Is the Objective-C not sending the XML in the right format?
Or is the Django server not processing that XML correctly?

Any insight would be much appreciated. Thanks in advance.

# Update:

I got it to work, by editing the iOS Controller to set the HTTPBody of the
request like so:

    
    
    NSMutableData *highScoreData = [NSMutableData data];
    [highScoreData appendData: [[NSString stringWithFormat: @"player_name=%@;", @"test"] dataUsingEncoding: NSUTF8StringEncoding]];
    [highScoreData appendData: [[NSString stringWithFormat: @"score=%d", 0] dataUsingEncoding: NSUTF8StringEncoding]];
    [request setHTTPBody: highScoreData];
    

For some reason putting a semicolon in there got Django to recognize it,
assign the values to a new instance of a HighScore class, and save it. The
logging on the test server indicates `request.POST` is `<QueryDict: {u'score':
[u'9'], u'player_name': [u'test']}>`.

Still not quite sure what to make of all this.

As per [Radu's](http://stackoverflow.com/users/549897/radu) suggestion, I took
a look at highScoreData with NSLog, right after appending it to
request.HTTPBody, and the result is `<706c6179 65725f6e 616d653d 74657374
3b73636f 72653d39>`.

I'm a huge Obj-C noob, so again, any help is appreciated! Thanks again.


Answer: Since you control both sides, I'd drop the complexity of xml encoding the data
and use RestKit or some other framework that makes it easy to communicate with
Django.

