Accessing POST wcf services from iPhone - iphone

I have been given url of an asp.net wcf service page which accepts few parameters as POST. But I am getting error code 400 when I try to access it.
url:
http://domain.w04.wh-2.com/IBServiceHost/IBService.svc/AddTask
I am also told to post json as below
{
"TaskId":"23",
"TaskDate":"6/27/2013",
"TaskDesc":"Test task",
"TaskName":"TestName",
"TaskStatus":true,
"ProjectId":"24",
"DbState":"Added"
}
My code to access the service:
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://mydomain.w04.wh-2.com"]];
client.parameterEncoding = AFJSONParameterEncoding;
NSMutableURLRequest *request =
[client requestWithMethod:#"POST" path:#"/IBServiceHost/IBService.svc/AddTask" parameters:dictTask];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSLog(#"JSON: %#", [JSON valueForKeyPath:#"LoginResult"]);
NSLog(#"Code: %#", [[[JSON valueForKeyPath:#"LoginResult"] valueForKeyPath:#"Code"] stringValue]);
NSLog(#"FaultString: %#", [[JSON valueForKeyPath:#"LoginResult"] valueForKeyPath:#"FaultString"]);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)
{
NSLog(#"request %#",request);
NSLog(#"response %#",response);
NSLog(#"error %#",error);
NSLog(#"error opening connection");
}];
[operation start];

Related

How to determine reason for failure with AFNetworking AFJSONRequestOperation

I've inherited a project and am implementing AFNetworking and reading the docs it sounds great and much simpler than the current code. I have a url with json data so I'm doing the following, but getting the failure block and no idea why. I'm sure it's there, but how can I dig into AF and log the responses to determine failure reason. I know the url works, but perhaps its hitting the url but having trouble parsing?
NSString *listURL = [NSString stringWithFormat:GET_LIST,BASE_URL];
NSURL *url = [NSURL URLWithString:briefListURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest: request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
self.list = [NSArray arrayWithArray:(NSArray *)JSON];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
[self listOperationDidFail];
}];
thanks to #Larme this worked:
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { NSLog(#"Error: %#", error); }
also, to answer my own issue above with text/plain. just add this before setting up operation:
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/plain"]];

Waiting for AFJSONRequestOperation to complete

I'm working with AFNetworking to get some JSON from the web. How can I get the response from the asynchronous request returned? Here's my code:
- (id) descargarEncuestasParaCliente:(NSString *)id_client{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://whatever.com/api/&id_cliente=%#", id_client]]];
__block id RESPONSE;
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
RESPONSE = JSON;
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"ERROR: %#", error);
}];
[operation start];
return RESPONSE;
}
I think you are confused about how blocks work.
That's an asynchronous request, therefore you cannot return any value computed inside the completion block, since your method already returned when it's executed.
You have to change your design an either perform a callback from inside the success block, or pass your own block and get it called.
As an example
- (void)descargarEncuestasParaCliente:(NSString *)id_client success:(void (^)(id JSON))success failure:(void (^)(NSError *error))failure {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://whatever.com/api/&id_cliente=%#", id_client]]];
__block id RESPONSE;
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
if (success) {
success(JSON);
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"ERROR: %#", error);
if (failure) {
failure(error);
}
}];
[operation start];
}
You will then call this method like follows
[self descargarEncuestasParaCliente:clientId success:^(id JSON) {
// Use JSON
} failure:^(NSError *error) {
// Handle error
}];

AFNetworking Expected content type error

I am getting the json string in failure block
NSURL *url = [[NSURL alloc] initWithString:#"http://www.vinipost.com/Services/Update/UpdateService.asmx/GetPropSubType?"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[AFJSONRequestOperation addAcceptableContentTypes:[NSSet setWithObject:#"text/html"]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"%#", JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
[operation start];
Output:
Request Failed with Error: Error Domain=AFNetworkingErrorDomain Code=-1016 "Expected content type {(
"text/json",
"text/javascript",
"application/json",
"text/html"
)}, got text/plain" UserInfo=0x71521a0 {NSLocalizedRecoverySuggestion=[{"PropTypId":1,"PropCatId":1,"PropTyp":"Flat/ Condo"}.......**
You need to add this line before operation
[AFJSONRequestOperation addAcceptableContentTypes:
[NSSet setWithObject:#"text/plain"]];
The error is clear:
the web service is returning a wrong content type.
The content type should be one of these:
"text/json",
"text/javascript",
"application/json",
"text/html"
But it returns
text/plain
Moreover, if you look at the http response, it returns HTML TAGS inside it, so AFNetworking is not able to parse.
If this page:
http://www.vinipost.com/Services/Update/UpdateService.asmx/GetPropSubType?
is under your control, correct the behavior removing html tags and changing the content type
In AFNetworking, you have to create NSURLRequest with the help of AFHTTPClient(So first you have to create AFHTTPClient and have to set some properties for this object) like below
AFHTTPClient *httpClient = [[httpClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://www.vinipost.com/"]];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
[httpClient setDefaultHeader:#"Accept" value:#"application/json"];
httpClient.parameterEncoding = AFJSONParameterEncoding;
now if depends of GET/POST or any other type request you need to set parameter I consider it as POST Request, so set the Parameter dict and set all required Key Value pairs properly.if no parameters required you can pass Parameters as nil
NSURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"Services/Update/UpdateService.asmx/GetPropSubType?" parameters:params];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
NSLog(#"%#",JSON);
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)
{
NSLog(#"Error MSG = %#",error);
}];
[operation start];
hope this will work for you :)

AFNetworking not returning data synchronously inside a block

Can't receive JSON synchronously inside a block using AFNetworking. I checked this solution. It
always nil at the end of method.
Here is my method:
- (BOOL)whois:(NSString *)domain withZone: (NSString*) zone
{
__block NSString *resultCode;
NSURL *url = [[NSURL alloc] initWithString:#"myurl"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
resultCode = [JSON valueForKeyPath:[NSString stringWithFormat:#"%#.%#", domain,zone]]; //checked with NSLog, works well
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation: operation];
[operation waitUntilFinished];
if(resultCode == #"available") //nil here
{
return YES;
}
return NO;
}
Instead of creating aNSOperationQueue, start your AFJSONRequestOperation with [operation start] and then call [operation waitUntilFinished] and it will block the main thread until it's finished. Then your resultCode should not be nil.
As #mattt said in the post you linked, it is strongly discouraged to freeze the thread like this. Consider figuring out another way to do this, such as calling a new method you hope to continue from your success block, and a different failure method from your failure block.
Your method can't function with its current design.
- (BOOL)whois:(NSString *)domain withZone: (NSString*) zone
{
__block NSString *resultCode;
NSURL *url = [[NSURL alloc] initWithString:#"myurl"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
// *** Runs 1st
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// *** runs 3rd
resultCode = [JSON valueForKeyPath:[NSString stringWithFormat:#"%#.%#", domain,zone]]; //checked with NSLog, works well
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
// *** Runs 2nd
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation: operation];
[operation waitUntilFinished];
if(resultCode == #"available") //nil here
{
return YES;
}
return NO;
}
Because the material in the block runs third, and asynchronously, you won't be able to return that value to the greater method in the manner it is currently designed. Perhaps use something like this:
- (void)whois:(NSString *)domain withZone: (NSString*) zone
{
NSURL *url = [[NSURL alloc] initWithString:#"myurl"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
__weak id weakSelf = self;
// Runs 1st
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSString *resultCode = [JSON valueForKeyPath:[NSString stringWithFormat:#"%#.%#", domain,zone]]; //checked with NSLog, works well
[weakSelf receivedResultCode:resultCode];
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Request Failed with Error: %#, %#", error, error.userInfo);
}];
}
- (void) receivedResultCode:(NSString *)resultCode {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation: operation];
[operation waitUntilFinished];
if(resultCode == #"available") //nil here
{
// do #YES stuff
}
else {
// do #NO stuff
}
}
Obviously you'll have to change the design of whoever's calling it because it won't return a value in the way you specified. Perhaps there is a better solution, but I think this is the type of design required for it to work.

Empty JSON returned by AFNetworking on iOS5

I'm trying to load a simple JSON inside my iPhone app using the AFNetworking library. I'm using two different approaches:
NSURL *url = [NSURL URLWithString:#"http://www.mysite.com/test.json"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Name: %#", [JSON valueForKeyPath:#"name"]);
} failure:^(NSURLRequest* req,NSHTTPURLResponse *req2, NSError *error,id mex) {
NSLog(#"%#", [error description]);
}];
[operation start];
and using AFHttpClient (which would be my favorite,since it has all the features for dealing with my REST API:
NSString *baseurl = #"http://www.mysite.com";
NSString *path = #"/test.json";
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:baseurl]];
[client registerHTTPOperationClass:[AFJSONRequestOperation class]];
//[client setAuthorizationHeaderWithUsername:#"myusername" password:#"mypassword"];
[client getPath:path parameters:nil success:^(AFHTTPRequestOperation *operation, id JSON) {
//NSLog(#"sjson: %#", [JSON valueForKeyPath:#"entries"]);
NSLog(#"sjson: %#", JSON);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error Code: %i - %#",[error code], [error localizedDescription]);
}];
now,the problem: in both cases I'm receiving an empty Json. I've tested the server side and the web-service is giving the right response and the right MIME type (application/json).
I've already checked this discussion https://github.com/AFNetworking/AFNetworking/issues/175
but my target is pointing to 5.0 and ARC is not enabled for the AFNetworking library.
Maybe I'm missing something obvious here,but I cannot fix it at the moment.
Thanks a lot!
Claus