JSON truncated when sent via NSMutableURLRequest to APS.NET MVC controller - objective-c

I am building a JSON post in objective-c and sending it to an ASP.NET MVC controller.
I am building the NSMutableURLRequest as follows:
request = [[NSMutableURLRequest alloc] initWithURL:url];
NSString* jsonRequest = [NSString stringWithFormat: #"{\"collection\":\"images\",\"id\":\"%#\",\"objectjson\":%#}",response.id,response.json];
NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody: requestData];
I then send the request as follows:
NSOperationQueue *backgroundQueue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:backgroundQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{ ... completion code goes here
This works well most of the time. However, for very large JSON strings I occasionally get a web service error where the web service reports that it is encountering an End of File marker within the JSON. It appears that the JSON is being truncated.
I am sending the JSON to an ASP.NET MVC controller.
Does anyone have any words of wisdom on what might be happening? Are there any ASP.NET web configuration settings that perhaps I need to adjust to prevent this issue occurring.
One thing I don't understand is why it is such an intermittent problem.

This seems to be a result of bytes being lost over 3G or EDGE connection. The best idea I can come up with is to detect on the server that the content length header is larger than the request POST body and to return a status code that tells the client to try again. The client could pass a retry count on the url and the server could read it and if it's a certain value, the server would return an error code indicating that a retry should not be attempted. Ugly I know but I can't think of a better way. This is what I am going to do for my photo uploading app.
Good luck!

the problem is in the conversion to NSData
try this
NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding];

Related

How do I POST JSON data object to server iOS8?

I want to send a new object created on iOS to a receiving server with a POST method using JSON data type. From what I know about receiving data from the server in iOS, is that all JSON handling was simplified by Apple with the introduction of iOS 8. But in contradistinction to GETting JSON objects, POSTing those isn't really described anywhere I could find ...
The first steps I took to try and solve the problem looked as follows:
How can I send the below format to server???
{"createFrom":"","createType":"","filename":"AC","filter":"","lstData":[{"FieldName":"LNK_RELATED_CN","FieldValue":""},{"FieldName":"LNK_RELATED_CO","FieldValue":""},{"FieldName":"MLS_PURPOSE","FieldValue":"Inquiry"},{"FieldName":"MLS_STATUS","FieldValue":"Open"},{"FieldName":"MMO_NOTES","FieldValue":""},{"FieldName":"DTE_NEXTACTIONDATE","FieldValue":""},{"FieldName":"MMO_NEXTACTION","FieldValue":""}],"password":"Infodat2","username":"manmeets","IsNew":true}
I have seen code like this:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:#"%#AssetSave",[defaults objectForKey:#"siteAddress"]]];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPBody:jsonData];
_responseData = [NSMutableData data];
NSLog(#"request : %#", request);
_nsurlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
But I really don't know how to send a JSON object to a server using a POST method at all. Could anybody please help me out?
The code you have is fine, you just need to create jsonData:
jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
(thought you should really also include an &error so you can see what's happening if something goes wrong)

Can't send data from objective-c via POST

i'm developing an app for iPhone and I'm stuck in one call, I have to send data via POST, the django web programmer tells me the app has to receive
param_one = request.POST['param_one']
param_two = request.POST['param_two']
but I cannot make it to send any data...
I'm learning objective-c, so please, could you tell me how to do it with an example?
PS: all the other calls that doesn't send any data, or pass data through url (GET method) works fine, so I'm making the connection correctly
Here's the code I'm using:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:#"somename" forKey:#"user"];
NSString *jsonString = [dict JSONRepresentation];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *  request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://web.com/custom/url/call/"]];
[request setValue:jsonString forHTTPHeaderField:#"json"];
[request setHTTPMethod:#"POST"];
[request addValue:csrf forHTTPHeaderField:#"X-CSRFToken"];
[request setHTTPBody:jsonData];
senddata = [[NSURLConnection alloc] initWithRequest:request delegate:self];
You should probably add:
[request setValue:#"application/json; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
Then the server will know that what you're sending is UTF-8 encoded JSON and it will be able to parse it appropriately. Otherwise it just gets a formless blob of data.
Unless it's for debugging purposes, it's very odd that you put the JSON string into both the header and the body.

Why does my NSURLMutableRequest POST request act like a GET request?

I've got a problem with my objective c code. I have a API-key protected WCF API that I built that takes POST requests and writes them to a Java servlet with C#. Anyway, this works great when testing with Fiddler, not so good from objective C. When I try to run the POST from my objective C, it "acts" like the NSURLMutableRequest is looking for a GET, in that the response only returns some default code I have written in for the GET method. Does anybody know why this is, and, moreover, what I can do to fix it? Here is the code that I use (quite successfully) to make other POST requests in with objective C.
is the problem the fact that I specify the API key in the URL for the NSMutableRequest? That's the only thing I can figure.
Here is the code:
NSString* theMessage = [NSString stringWithFormat:#"<MyRequestObject xmlns='http://schemas.datacontract.org/2004/07/MyService'></MyRequestObject>"];
NSMutableURLRequest *theRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:POST_API_URL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:240.0];
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:#"text/xml" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPBody:[theMessage dataUsingEncoding:NSUTF8StringEncoding]];
NSString *msgLength = [NSString stringWithFormat:#"%d", [theMessage length]];
[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
NSURLResponse* response;
NSError *error;
NSData* result = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
I ended up using ASIHTTPRequest to run the POST request to the WCF REST service, and now everything seems to be running smoothly. This means that there's probably some sort of URL Encoding mechanism for the API key that's going on behind the scenes that was poorly documented for NSMutableURLRequest, who knows. The good thing is, I've got the issue fixed. Here is the code I used:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:POST_API_URL]];
[request appendPostData:[[NSString stringWithFormat:#"<MyRequest xmlns='http://schemas.datacontract.org/2004/07/MyService'>all of my request params in here</MyRequest>"] dataUsingEncoding:NSUTF8StringEncoding]];
[request setRequestMethod:#"POST"];
[request addRequestHeader:#"Content-Type" value:#"text/xml"];
[request startSynchronous];
Did you try setting the Content-Length header? WCF/IIS might be ignoring the body if it doesn't have its length defined in as a header.

Properly handling NSURLConnection errors

I have a simple form interface set up that send username and password information to a server: (working)
NSString *postData = [NSString stringWithFormat:#"user=%#&pass=%#",[self urlEncodeValue:sysUsername],[self urlEncodeValue:password]];
NSLog(#"Post data -> %#", postData);
///
NSData* postVariables = [postData dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] init] autorelease];
NSString* postLength = [NSString stringWithFormat:#"%d", [postVariables length]];
NSURL* postUrl = [NSURL URLWithString:#"http://localhost/~csmith/cocoa/test.php"];
[request setURL:postUrl];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: postVariables];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:NULL];
NSLog(#"Post data SENT & returned -> %#", returnData);
How do I handle connection errors such as no internet connection, firewall, etc.
Also, does this method use the system-wide proxy settings? Many of my users are behind a proxy.
Thanks a lot!
First, you shouldn't use synchronous requests, use asynchronous request instead and indicate activity using indeterminate progress indicators.
When using asynchronous requests, you have to set a delegate implement delegate methods, notably:
-connectionDidFinishLoading:
-connection:didFailWithError:
From the docs:
Unless a NSURLConnection receives a cancel message, the delegate will receive one and only one of connectionDidFinishLoading:, or connection:didFailWithError: message, but never both. In addition, once either of messages are sent, the delegate will receive no further messages for the given NSURLConnection.
As for the last question:
Also, does this method use the system-wide proxy settings?
Yes, NSURLConnection uses them automatically.
You should use asynchronous request to handle proxy and network errors. This is more efficient.
To add extra check you can add reach-ability test in your code before communications. you can find reach-ability test code here

using JSON-Framework to prepare a json object to post via HTTP Request Objective-C

I am successfully using the json-framework to do GET HttpRequests. Does anyone have code to prepare a json object and do a POST HTTP Request? If so, can you please share some sample objective-c code. Thanks
Take a look at this open source project hosted at google code.
Description:
This framework implements a strict JSON parser and generator in Objective-C.
Download the framework, embed it in your application, and import the JSON.h header. You're now ready to make your application speak JSON. The framework adds categories to existing Objective-C objects for a super-simple interface, and provides classes with more flexible APIs for added control.
Try TwitterHelper.m in Stanford's CS 193P "Presence3Files.zip" package.
I would post the code directly but am unsure if that is cool, license-wise.
USe following code for making a Post Request using JSON Data Object.
self.responseData=[NSMutableData data];
NSURL *url = [NSURL URLWithString:#"http://dev.iworklab.com/myProject/index.php"];
NSString *jsonRequest = [NSString stringWithFormat:#"{\"method\":\"changePassword\",\"customer_id\":\"%#\",\"old_password\":\"%#\",\"new_password\":\"%#\",\"con_password\":\"%#\"}",customerID,oldPasswordText.text,newPasswordText.text,confirmPasswordText.text];
jsonRequest = [NSString stringWithFormat:#"&json_data=%#",jsonRequest];
NSData *json_data = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody: json_data];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [json_data length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:[[jsonRequest stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]
dataUsingEncoding:NSUTF8StringEncoding
allowLossyConversion:YES]];
passwordConnection = [NSURLConnection connectionWithRequest:request delegate:self];