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.
Related
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)
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];
The goal is to do a simple username/password authentication by querying a database. Until the connection is working decently my php destination file simply has following code:
echo "Posted: " . $_POST['email'];
The code to do this synchronously is this:
NSString *post = [[NSString alloc] initWithFormat:#"email=%#&password=%#", self.email.text, ..]; // .. simplified keychainItem
NSData *postEncoded = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSString *postLength = [NSString stringWithFormat:#"%d", [postEncoded length]];
NSURL *url = [NSURL URLWithString:#"http://eng.studev.groept.be/web2.0/a11_web02/improver/app/testPost"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postEncoded];
NSError *error = nil;
NSURLResponse *response = nil;
NSData *encodedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *data=[[NSString alloc]initWithData:encodedData encoding:NSUTF8StringEncoding];
NSLog(#"Data? %#",data);
The correct value is shown as an echo. But when trying to do this asynchronously, I get following php error: "Undefined index: email".
I try to start the asynchronous request with this line:
[[NSURLConnection connectionWithRequest:request delegate:self] start];
Then, I have the delegate method connection:didReceiveResponse, but there I cannot seem to get the data out... Or do I need another delegate method? Also, how 'safe' is it to check the result of your query by using just an echo (do I need/want a stream maybe?) ??
Tia
EDIT
Problem related to the server, not to objective-C code. Asked a new question to reach the correct audience: $_POST remaining empty
#ott is on the right track, I'll try to clarify.
You don't need start as he says. It's benign as the connection will start automatically.
initWithRequest:delegate and connectionWithRequest:delegate: are equivalent except for the retain state of the new connection object.
The real problem is b/c you are using connectionWithRequest:delegate the returned connection is autoreleased at the end of the run loop and you are not retaining it in a property. Therefore, the connection never starts.
The solution is to add a property #property (nonatomic, retain) NSURLConnection *connection to your class and set this property to the connection returned from connection:withRequest:
You then release the connection in the completion methods connection:didFinishLoading and connection:didFailWithError:.
The start is wrong here. Simply use
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
with NSURLConnection *connection; defined. See the class reference for connectionWithRequest. start is to be used with initWithRequest:delegate:.
I'm building a request that will be a simple http POST. Inside this post I need to add a few items and one of these is a large viewstate string that is pulled down during a previous request. What I've noticed is that the raw request needs to have all special chars escaped (like the below)
_EVENTTARGET=&_EVENTARGUMENT=&__VIEWSTATE=%2FwEPDwUENTM4MQ9kFgJmD2QWAmYPZBYCZg9kFgJmD2QWAgIBEGRkFgQCAQ9kFgICBw9kFgJmD2QWCmYPFgIeA3NyYwUpL2Fzc2V0cy9pbWFnZXMvc2l0ZW1haW5uYXYtcmVudG9ubGluZS5wbmdkAgEPFgIfAAUlL2Fzc2V0cy9pbWFnZXMvc2l0ZW1haW5uYXYtc3BhY2VyLnBuZ2QCAg8WAh8ABSUvYXNzZXRzL2ltYWdlcy9zaXRlbWFpbm5hdi1tb3ZpZXMucG5nZAIDDxYCHwAFJS9hc3NldHMvaW1hZ2VzL3NpdGVtYWlubmF2LXNwYWNlci5wbmdkAgQPZBYCZg9kFgZmDxYCHwAFLi9hc3NldHMvaW1hZ2VzL3NpdGVtYWlubmF2LWtpb3Nrc2Fub255bW91cy5wbmdkAgEPFgIfAAUlL2Fzc2V0cy9pbWFnZXMvc2l0ZW1haW5uYXYtc3BhY2VyLnBuZ2QCAg8WAh8ABSgvYXNzZXRzL2ltYWdlcy9zaXRlbWFpbm5hdi1idXlPbmxpbmUucG5nZAICD2QWAgIBD2QWAgIGD2QWAgIBD2QWAmYPZBYCAgIPEA8WAh4EVGV4dAVTUmVjb2duaXplIG1lIGZvciAxNCBkYXlzIChEbyBub3QgY2hlY2sgdGhpcyBib3ggaWYgeW91IGFyZSB1c2luZyBhIHNoYXJlZCBjb21wdXRlcilkZGRkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBVVjdGwwMCRjdGwwMCRjdGwwMCRjdGwwMCRNYWluQ29udGVudCRNYWluQ29udGVudCRNYWluQ29udGVudCRiYnhsb2dpbl83JGNoa1JlY29nbml6ZU1lNZH1xfrz8glwi2XmQJFTCJ0dMNk%3D&
But I'm not certain that I've done this in objective-c. Currently when I NSLog out the viewstate string it is still showing / and = characters.
Can anyone verify I'm on the right path here? And if not how would I convert the special chars in viewstate (ie - instead of = I should get %3D)?
- (void)doHttpPostWithViewState:(NSString *)viewstate
{
responseData = [[NSMutableData data] retain];
NSURL *url = [NSURL URLWithString:#"https://localhost/Login"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSString* theBodyString = [[NSString alloc] initWithFormat:#"__EVENTTARGET=&__EVENTARGUMENT=&__VIEWSTATE=%#",viewstate];
NSData *requestData = [theBodyString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary * headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody: requestData];
[request setAllHTTPHeaderFields:headers];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
And finally, for local debugging purposes- how can I use NSLog to view the final (raw) string that will be sent to the client? Thank you in advance!
Update
Turns out this is a bug in the stringByAddingPercentEscapesUsingEncoding method
I've found the following to work from this blog post
NSString * cleanViewState = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)viewstate,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 );
You're probably looking for the stringByAddingPercentEscapesUsingEncoding: method on NSString to %-encode your POST request.
Update:
If the NSString method isn't getting all the special characters you need, the next step is to drop down to the Core Foundation level function (CFURLCreateStringByAddingPercentEscapes), which gives you better control. See http://simonwoodside.com/weblog/2009/4/22/how_to_really_url_encode/
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];