Why does my NSURLMutableRequest POST request act like a GET request? - objective-c

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.

Related

NSURLRequest the request time out

I've a strange problem, I'm working on a project that I've to request from a server, When requesting a URL without parameters using GET method, it works fine and return the desired data, but when using the same code to call the URL and sending a parameters to it, it fail with this error:
error: Error Domain=NSURLErrorDomain Code=-1001 UserInfo=0xed4870 "timed out"
My code is the following:
NSString *param = #"pageNumber=2";
NSURL *url = [NSURL URLWithString:#"http://myWebsite/api/Soccor/"];//When using this, it works fine
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://myWebsite/api/Soccor?%#", param]];//When using this, it gives me the request time out error.
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
[theRequest addValue:#"application/json;charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue:#"application/json" forHTTPHeaderField:#"Accept"];
[theRequest addValue:msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"GET"];
[theRequest setTimeoutInterval:10];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
Any clue why it returns error when sending parameters with the URL?
I would suggest you consider two aspects of the request:
You are not showing us your setting of msgLength, but I would only suggest setting a Content-Length header if you're also using setHTTPBody, in which case you'd set the Content-Length to be the length of the NSData you use as a parameter to setHTTPBody. But this is used with POST requests, not GET requests.
You specify application/json for the Content-Type of the request, but request does not consist of JSON. If you did that because the response is JSON, it should be noted that this header value is for your request, not for the response you expect from the server.

NSURLRequest setValue: forHTTPHeaderField:#"Authorization" not working

I try to make an authenticate call to the twitter API with the Application only Authentication API
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:20.0];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"Some App Name" forHTTPHeaderField:#"User-Agent"];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
[request setHTTPBody:[#"grant_type=client_credentials" dataUsingEncoding:NSUTF8StringEncoding]];
Interestingly the authValue is not getting set for HTTPHeaderField #"Authorization". Therefor my calls fail of course. All other header fields are set correctly.
I check it by
NSLog(#"Authorization, %#, %#", [request valueForHTTPHeaderField:#"Authorization"], authValue);
which returns #"Authorization, (null), theCorrectStuff
Why is this happening? I should be able to set it right away, or am I missing something?
Thanks for your time and consideration,
Fabian
I had the same issue. Output your authValue, it probably contains new lines. For the application only authentication after you do base64 you need to remove new lines from authValue otherwise the header field won't be set.
Or just use already written Objective-C library for Twitter REST API 1.1 (https://github.com/nst/STTwitter).

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

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];

NSURLConnection Unable to http post large file

We are trying to add in functionality into our app to allow it to POST a large file approx 50kb to our web service the file itself is a HTML template, however with the code below what we are finding is that the data seems to get cut off when the web service saves it.
The web service is currently designed to check the $_POST['html'] variable and write it to a file.
Is there a better way to do this and does anyone have any idea why the upload is not complete?
Thanks Aaron
NSString *myText;
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"template" ofType:#"htm"];
if (filePath) {
myText = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
}
NSURL *URL = [NSURL URLWithString:#"http://mywebsiteurl.com/receiveData.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
request.HTTPMethod = #"POST";
NSString *params = [NSString stringWithFormat:#"html=%#", myText];
NSData *data = [params dataUsingEncoding:NSASCIIStringEncoding];
[request addValue:#"8bit" forHTTPHeaderField:#"Content-Transfer-Encoding"];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request addValue:[NSString stringWithFormat:#"%i", [data length]] forHTTPHeaderField:#"Content-Length"];
[NSURLConnection connectionWithRequest:[request autorelease] delegate:self];
I think it is because your Server set the post limit.Check the settings at your server side about the post data limit.
When I rechecked this question, I think maybe I found what was the problem. When I do HTTP post, I usually don't set the content-length by myself. I just encode my post data as key=value&.. form and use the [NSMutableURLRequest setHTTPBody:data] method to add the data to the NSMutableURLRequest. I think it will do the rest for you include set the content-length for you. Even though I am not very familiar with HTTP protocol, but I think maybe the content-length represent the whole post data length, but here you set the content-length value with the length of key value data length.

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];