I have a Windows based REST Server built using Microsoft-HTTPAPI (i.e. its not running under IIS)
If I send a JSON request to the service from a browser based REST tool (Firefox RESTClient) the server receives the request and processes it correctly as per the traces from the Microsoft Service Trace Viewer and the response from the service. I receive valid JSON back from the service.
I have an iOS application that uses a NSURLConnect to send the VERY SAME JSON request to the service, but it always times out. I've traced using WireShark, and the HTTP request is correctly formed and sent correctly to the server in both cases. I've traced using the MS Trace Viewer and it goes into "receive Bytes" but never returns. I get an exception when I eventually close the WCF Server.It never returns when I close the iOS app.
I have tried using NSURLConnection sendSynchronousRequest and asynchronously using the callbacks and asynchronously using completion blocks. If I make the timeout 0, the call (to sendSynchronousRequest) never returns. In all other cases, I get a timeout, and the WCF never completes the receive bytes part of the WCF invocation (a POST request)
I've checked
Here's my iOS Code:
dispatch_queue_t myQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(myQ, ^{ // First Queue the parsing
#try {
//Generate endpoint url
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/%#",appState.posPostingURL,serviceName]];
//Setup request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:10.0];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", #"xxxx", #"xxxx"];
NSString *authData = [NSString base64StringFromString:authStr];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", authData];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
//Setup request headers
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"no-cache" forHTTPHeaderField:#"Cache-Control"];
[request setValue:[NSString stringWithFormat:#"%d", [dataBuffer length]] forHTTPHeaderField:#"Content-Length"];
// Put the request data in the request body
[request setHTTPBody: dataBuffer];
NSHTTPURLResponse *urlResponse = nil;
NSError *error = nil;
// and send to the server synchronously
serverData = [[NSURLConnection sendSynchronousRequest:request
returningResponse:&urlResponse
error:&error] mutableCopy];
// Now check the status and response
if (error) {
My WCF Code is as follows
namespace MyWebService{
[ServiceContract(Name = "MyServiceIntegrator", Namespace = "")]
public interface IMyIntegrator
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/Configure",
BodyStyle=WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
Result Configure(MyServerConfig config);
In the app.config file, the service endpoint is configured with
binding="webHttpBinding"
The Trace view is as follows:
Could there be any reason on either side that the server does not complete the read even though the JSON is valid.
I have also checked NSURLConnection JSON Submit to Server
and as far as I can see my code to send the request is correct.
Any ideas - Been pulling my hair out for 3 days now
What happens if you change this:
[request setValue:[NSString stringWithFormat:#"%d", [dataBuffer length]] forHTTPHeaderField:#"Content-Length"];
To this:
[request setValue:[NSString stringWithFormat:#"%i", [dataBuffer length]] forHTTPHeaderField:#"Content-Length"];
Probably won't make a difference, but the rest of your code looks fine so maybe worth a shot. (My thinking is the decimal is causing the server issues).
ferdil,I think you can try changing timeout period to 30.0 instead of 10.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:30.0];
Related
For send data from POST method using windows azure mobile service .
Getting response error response
message = "An error has occurred."
My post method is and
data dictionary is
NSDictionary *data = #{#"emailID": #"abc#gmail.comt",
#"userPhone": #"",
#"password": #"12345678",
#"id":#"",
#"signUpBy": [NSNumber numberWithInt:1]};
And API call function is is
-(void)signUpCallAPI:(NSDictionary *)parameter{
// URL that calls into the Azure Service
NSString *serviceUri = #"https://demo.azure-mobile.net/tables/SignUp";
// Convert to NSURL type
NSURL *myURL = [NSURL URLWithString:serviceUri];
// Create a request object
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
NSError *error;
NSData *jsonData = nil;
if (parameter)
jsonData = [NSJSONSerialization dataWithJSONObject:parameter
options:NSJSONWritingPrettyPrinted
error:&error];
// Modify http headers for POST request
[request setHTTPMethod: #"POST"];
//Content type what we are sending
[request setValue:[NSString stringWithFormat:#"%lu",(unsigned long)jsonData.length ] forHTTPHeaderField:#"content-length"];
// Indicate JSON Data Format
[request setValue:#"application/json" forHTTPHeaderField:#"content-type"];
// Indicate JSON Data Format
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
// Indicate host property
[request setValue:#"demo.azure-mobile.net" forHTTPHeaderField:#"Host"];
// Indicate application key (you get this from the portal)
[request setValue:#"demoappkey" forHTTPHeaderField:#"X-ZUMO-APPLICATION"];
//add data to body
[request setHTTPBody:jsonData];
// Execute request
conn= [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];}
For Post data from signup api not working .
Anything need to do my side?
Any sample available for for post data using API.
Thanks in advance
Looks like you're trying to use Mobile Services without using the iOS SDK. Microsoft has created an SDK for various mobile platform that simplify sending and retrieving data from Mobile Services: https://github.com/Azure/azure-mobile-services
I'd suggest you first look at the ToDo sample iOS app: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-ios-get-started/
Next, this article in the Microsoft documentation explains how to add Mobile Services to an existing app: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-ios-get-started-data/
Is there a mechanism in Objective-C similar to Netty in Java for diverting TCP to UDT protocols in Transport Layer.
Now I want to implement HTTP request and response (runs over TCP by default) to run over UDT from my application.
Is this possible?
Is there any in-built mechanism in iOS for this?
If you would like to use HTTP than I suggest NSURLConnection class. For example to use POST request with headers do something like this:
int kTimeoutInterval = 30;
NSString *post = #"Something to post";
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
NSString *link = #"http://some_link";
link = [link stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:link] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:kTimeoutInterval];
[request setURL:[NSURL URLWithString:link]];
[request setHTTPMethod:#"POST"];
// set some header entries, for example:
//[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
//[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[postLength length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSError *error;
NSURLResponse* response=nil;
NSData* data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
Now be careful, this is a synchronous request, and it will block the thread on which it is run for the execution time or timeout time that is defined in kTimeoutInterval constant. This can be changed to async mode with:
[NSURLConnection connectionWithRequest...
in which case the response will come through delegate method. So to decide which approach works best for you, go through NSURLConnection documentation. Hope this helps...
There isn't anything quite as convenient as Netty. However you might want to take a look at the CFNetwork programming guide, specifically the sections on Communicating with HTTP Servers. This describes the CFHTTPMessage methods which can be used to create, and serialise, HTTP requests, and decode responses. As they serialise to, and decode from, buffers, you are free to transmit the messages however you like. If you already have a UDT implementation then it should be reasonably straightforward.
Note you are responsible for encoding / decoding the HTTP body appropriately but if your web service protocol is fairly simple that might only be a case of serialising / deserialising strings.
I have search around and can't quite find the right answer to this, but I have this code which posts data to my web server, and I am trying to get the HTTP response, but the response keeps returning (null). I can confirm that the connection is successful because the if statement (see below) executes the appropriate code.
Here is my code:
-(void)submitAction{
NSString *post = [NSString stringWithFormat:#"&var1=%#&var2=%#&var3=%#&var4=%#",
_var1, _var2, _var3, _var4];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d",[postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://my-web-server.com/path-to-web-service/"]]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Current-Type"];
[request setHTTPBody:postData];
NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:request delegate:self];
NSURLResponse *response;
NSLog(#"%#", response); // Always returns null :(
if(conn){
NSLog(#"Connection Successful."); // Connection is successful in my tests.
}else{
NSLog(#"Connection could not be made");
}
}
Here is the NSURLConnectionDelegate delegate implemented in my .h file:
#interface AddTaskViewController : UIViewController <UITextFieldDelegate, UIPickerViewDelegate, NSURLConnectionDelegate>
Can anyone see what I am doing wrong here? The server should return a JSON string, (and it does when I test the web service via my browser) but the NSURLResponse is constantly null.
Thanks,
Peter
Using initWithRequest:delegate: of NSURLConnection starts an asynchronous download, so it returns immediately and executes straight away.
response is always nil because you just defined it and then logged it without ever setting it to anything. That needs to be done in the connection:didReceiveResponse: delegate method.
Where you do if(conn){, the conn existing doesn't mean the connection was successful, it just means that the connection could be created (basically, you didn't supply an invalid request). You don't know whether it's going to work yet.
Implement the delegate methods from NSURLConnectionDelegate_Protocol (and NSURLConnectionDataDelegate) to get access to the response and downloaded data (when it becomes available).
I'm trying to use NSURLConnection sendSynchronousRequest: to send a binary file (an JPEG image) to a server. The code I have is:
// url contains the URL of the remote server.
// fileURL contains the URL for the local file to be sent.
request = [NSMutableURLRequest requestWithURL:url];
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPMethod:#"PUT"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"image/jpeg" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBodyStream:[NSInputStream inputStreamWithURL:fileURL]];
responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&requestError];
if (requestError != nil) {
NSLog(#"%#", requestError);
return NO;
}
This almost works. The remote server receives the request properly, and responds with an appropriate JSON object. But sendSynchronousRequest: blocks until the timeout value, and then reports a timeout.
Elsewhere, I'm able to send and receive JSON objects properly using pretty much this same code pattern, so I'm baffled why this one would be timing out.
I've successfully implemented push notifications with Urban Airship in my app, but I want to make an administrative password-protected part of the app that enables one to send the push notifications from any authorized iPhone with the app installed.
I need a way so whatever i type in a text box is send via https POST to https://go.urbanairship.com/api/push/broadcast.
Can anyone recommend or tell me a way to do this?
You can use NSURLConnection to do this. Setup an NSMutableURLRequest with the post data and other information, and then use NSURLConnection to post it and get a response:
NSString * postString = [NSString stringWithFormat:#"field1=%#", myItem];
NSData * postData = [postString dataUsingEncoding:NSUTF8StringEncoding];
NSURL * myURL = [NSURL URLWithString:#"https://go.urbanairship.com/api/push/broadcast"];
NSMutableURLRequest * request = [[NSMutableURLRequest alloc] initWithURL:myURL
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:10];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [postData length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
NSData * returnedData = [NSURLConnection sendSynchronousRequest:request
returningResponse:nil error:nil];
You can also use NSURLConnection for asynchronous requests. See the NSURLConnection Class Reference.