AFJSONParameterEncoding in AFNetworking 2.x.x - ios

I am implementing following paypal REST API:
curl -v https://api.sandbox.paypal.com/v1/vault/credit-card \
-H 'Content-Type:application/json' \
-H 'Authorization: Bearer {accessToken}' \
-d '{
"payer_id":"user12345",
"type":"visa",
"number":"4417119669820331",
"expire_month":"11",
"expire_year":"2018",
"first_name":"Joe",
"last_name":"Shopper"
}'
I have successfully implement this api in AFNetworking 1.3.3 with following Code. Where PPWebService is subclass of AFHTTPClient
[[PPWebService sharedClient] setParameterEncoding:AFJSONParameterEncoding];
[[PPWebService sharedClient] setDefaultHeader:#"Content-Type" value:#"application/json"];
[[PPWebService sharedClient] setDefaultHeader:#"Authorization" value:[NSString stringWithFormat:#"Bearer %#", accessToken]];
[[PPWebService sharedClient] postPath:#"vault/credit-card"
parameters:creditCard
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *response = [self JSONToObject:operation.responseString];
creditCardId = response[#"id"];
if(creditCardId)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Credit card" message:#"Saved !!" delegate:nil cancelButtonTitle:#"on" otherButtonTitles:nil];
[alert show];
}
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Credit card" message:error.description delegate:nil cancelButtonTitle:#"on" otherButtonTitles:nil];
[alert show];
}];
I want to use AFNetworking 2.x.x in my project. But I am not able to do it with this new version.
I have subclass AFHTTPRequestOperationManager. I search internet and people suggest me to use AFJSONRequestSerializer. All other code is very similar. But than also I am getting bad request error.
So how can I send raw JSON string in with POST method in AFNetworking 2.x.x?
EDIT
Code for AFNetworking 2.X.X
Error Status : 404 Bad Request
Response :
{"name":"MALFORMED_REQUEST","message":"The request JSON is not well formed.","information_link":"https://developer.paypal.com/docs/api/#MALFORMED_REQUEST","debug_id":"ab3c1dd874a07"}
I am getting proper response by using Postman as shown in following screenshot.

So finally I got answer. I use subclass of AFHTTPSessionManager to implement API in my project. And use it with singleton object. So this is my singleton method.
+ (MASWebService *)APIClient
{
static MASWebService *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
NSURL *baseURL = [NSURL URLWithString:BaseURL];
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
_sharedClient = [[MASWebService alloc] initWithBaseURL:baseURL sessionConfiguration:config];
_sharedClient.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
_sharedClient.requestSerializer = [AFJSONRequestSerializer serializer];
[_sharedClient.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
});
return _sharedClient;
}
The main key line is setting Request Serializer HTTP Header "Content-Type" to "application/json"
If you are not subclassing AFHTTPSessionManager and using AFHTTPRequestOperationManager for single request than also it will work because AFHTTPRequestOperationManager is also conform to AFURLRequestSerialization protocol as property of AFHTTPRequestSerializer. I have not done it but it should look like this.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"foo": #"bar"};
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[manager POST:#"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
I hope this will work. Inform me in comment if I am wrong somewhere.
Source : AFNetworking 2.0 POST request working example code snippet

So how can I send raw JSON string in with POST method in AFNetworking 2.x.x?
I had the same issue when trying to use SOAP+XML data with AFHTTPRequestOperationManager. Apparently the request serializer should be subclassed to make provision for your special serialisation needs, but this way seems easier:
NSError *error = nil;
NSData *envelopeData = [NSJSONSerialization dataWithJSONObject:params options:options error:nil];
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:#"POST"
URLString:path
parameters:nil
error:&error];
// In my case, I also needed the following:
// [request setValue:action forHTTPHeaderField:#"SOAPAction"];
[request setHTTPBody:envelopeData];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] init];
operation = [self HTTPRequestOperationWithRequest:request
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
// parse response here
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
// parse response here
}];
It hijacks the request serialiser that is created by AFHTTPRequestOperationManager, inserts the parameter data into the HTTP body, and then passes this new request into the AFHTTPRequestOperation.

Related

Unable to post JSON Using afnetworking in ios

I am getting this error while posting json to url :
Invalid top-level type in JSON write'
I am even sending perfect JSON using afnetworking post request code But it keeps giving me error.
My code :
NSString * serviceType = #"xyz";
NSString * remarks =#"project deadline is near ";
NSString * emailId = #"xyx.live.com";
NSDictionary *params =
# {
#"serviceType" :serviceType,
#"remarks" :remarks,
#"emailId" :emailId
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:params
options:0
error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager2 = [AFHTTPRequestOperationManager manager];
AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer];
[serializer setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[serializer setValue:#"application/json" forHTTPHeaderField:#"Accept"];
manager2.requestSerializer = serializer;
[manager2 POST:#"http://xyx.com" parameters:jsonString success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON_post_fzzlogin: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//here is place for code executed in success case
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error while sending POST"
message:#"Sorry, try again."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
NSLog(#"Error: %#", error);
}];
Please help me out this regard .thanks in advance
You are trying to encode request twice because you set request serializer for AFHTTPRequestOperationManager and provide parameters as encoded JSON string. So you need to provide raw parameters if you want to use request serializer or don't use it and encode to JSON manually.
This is how you post JSON or rather NSDictionary by AFNetworking
NSDictionary *dict = #{#"Key":#"Value"};
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager POST:[Util urlAppend:kListOfArticleCatagory] parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary *responseObj = (NSDictionary *)responseObject;//casting to NSDictionary from id
NSLog(#"%#",responseObj);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Something went wrong :%#",operation.responseString);
}];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
}
You dont post JSON through AFNetworking, rather the NSDictionary as the parameters, it will get converted to JSON as you post it.

Request failed: unacceptable content-type: text/html [duplicate]

I'm trying out the new version 2.0 of AFNetworking and I'm getting the error above. Any idea why this is happening? Here's my code:
NSURL *URL = [NSURL URLWithString:kJSONlink];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[[NSOperationQueue mainQueue] addOperation:op];
I'm using Xcode 5.0.
Also, here's the error message:
Error: Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: text/html" UserInfo=0xda2e670 {NSErrorFailingURLKey=kJSONlink, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0xda35180> { URL: kJSONlink } { status code: 200, headers {
Connection = "Keep-Alive";
"Content-Encoding" = gzip;
"Content-Length" = 2898;
"Content-Type" = "text/html";
Date = "Tue, 01 Oct 2013 10:59:45 GMT";
"Keep-Alive" = "timeout=5, max=100";
Server = Apache;
Vary = "Accept-Encoding";
} }, NSLocalizedDescription=Request failed: unacceptable content-type: text/html}
I just hid the JSON using kJSONlink. This should return a JSON.
This means that your server is sending "text/html" instead of the already supported types.
My solution was to add "text/html" to acceptableContentTypes set in AFURLResponseSerialization class. Just search for "acceptableContentTypes" and add #"text/html" to the set manually.
Of course, the ideal solution is to change the type sent from the server, but for that you will have to talk with the server team.
Setting my RequestOperationManager Response Serializer to HTTPResponseSerializer fixed the issue.
Objective-C
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
Swift
manager.responseSerializer = AFHTTPResponseSerializer()
Making this change means I don't need to add acceptableContentTypes to every request I make.
I took #jaytrixz's answer/comment one step further and added "text/html" to the existing set of types. That way when they fix it on the server side to "application/json" or "text/json" I claim it'll work seamlessly.
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
On the server side, I added:
header('Content-type: application/json');
into my .php code and this also fixed the problem.
I solve this problem from a different perspective.
I think if the server sends JSON data with Content-Type: text/html header. It doesn't mean the server guy intended to send you some html but accidentally changed to JSON. It does mean the server guy just doesn't care about what the Content-Type header is. So if the server guy doesn't care as the client side you better ignore the Content-Type header as well. To ignore the Content-Type header check in AFNetworking
manager.responseSerializer.acceptableContentTypes = nil;
In this way the AFJSONResponseSerializer (the default one) will serialize the JSON data without checking Content-Type in response header.
A simple way to enable to receive "text/plain" content type:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/plain"];
Similarly if you wish to enable "text/html" content type:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
I tried below line as per #Andrie answer but didn't work,
op.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
so after hunting more, I did work around to get it work successfully.
Here is my code snip.
AFHTTPRequestOperationManager *operation = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
AFJSONResponseSerializer *jsonResponseSerializer = [AFJSONResponseSerializer serializer];
NSMutableSet *jsonAcceptableContentTypes = [NSMutableSet setWithSet:jsonResponseSerializer.acceptableContentTypes];
[jsonAcceptableContentTypes addObject:#"text/plain"];
jsonResponseSerializer.acceptableContentTypes = jsonAcceptableContentTypes;
operation.responseSerializer = jsonResponseSerializer;
Hope this will help someone out there.
This is the only thing that I found to work
-(void) testHTTPS {
AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
[securityPolicy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setSecurityPolicy:securityPolicy];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:[NSString stringWithFormat:#"%#", HOST] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"%#", string);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
If someone is using AFHTTPSessionManager then one can do like this to solve the issue,
I subclassed AFHTTPSessionManager where I'm doing like this,
NSMutableSet *contentTypes = [[NSMutableSet alloc] initWithSet:self.responseSerializer.acceptableContentTypes];
[contentTypes addObject:#"text/html"];
self.responseSerializer.acceptableContentTypes = contentTypes;
In my case, I don't have control over server setting, but I know it's expecting "application/json" for "Content-Type". I did this on the iOS client side:
manager.requestSerializer = [AFJSONRequestSerializer serializer];
refer to
AFNetworking version 2 content-type error
Just add this line :
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
A good question always have multiple answers, to reduce and help you choose the right answer, here I am adding my own too. I have tested it and it works fine.
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"http://www.yourdomain.com/appname/data/ws/index.php/user/login/"]];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:#"POST" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *json = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"%#", json);
//Now convert json string to dictionary.
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error.localizedDescription);
}];
I had a somehow similar problem working with AFNetworking from a Swift codebase so I'm just leaving this here in the remote case someone is as unlucky as me having to work in such a setup. If you are, I feel you buddy, stay strong!
The operation was failing due to "unacceptable content-type", despite me actually setting the acceptableContentTypes with a Set containing the content type value in question.
The solution for me was to tweak the Swift code to be more Objective-C friendly, I guess:
serializer.acceptableContentTypes = NSSet(array: ["application/xml", "text/xml", "text/plain"]) as Set<NSObject>
UIImage *image = [UIImage imageNamed:#"decline_clicked.png"];
NSData *imageData = UIImageJPEGRepresentation(image,1);
NSString *queryStringss = [NSString stringWithFormat:#"http://119.9.77.121/lets_chat/index.php/webservices/uploadfile/"];
queryStringss = [queryStringss stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[manager POST:queryStringss parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
[formData appendPartWithFileData:imageData name:#"fileName" fileName:#"decline_clicked.png" mimeType:#"image/jpeg"];
}
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *dict = [responseObject objectForKey:#"Result"];
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];

AFNetworking version 2 content-type error

I'm attempting to make an iphone app that will interact with a particular JIRA server. I've got the following code to log in:
NSURL *url = [[NSURL alloc] initWithString:#"https://mycompany.atlassian.net/rest/auth/latest/session/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
NSString *postString = [NSString stringWithFormat:#"{\"username\":\"%#\",\"password\":\"%#\"}", username, password];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept" ];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"ERROR: %#", error);
}
];
[operation start];
But it's giving me the following error having to do with Content-Type:
ERROR: Error Domain=AFNetworkingErrorDomain Code=-1011
"Request failed: unsupported media type (415)"
UserInfo=0x8cd6540
{
NSErrorFailingURLKey=https://mycompany.atlassian.net/rest/auth/latest/session/,
NSLocalizedDescription=Request failed: unsupported media type (415),
NSUnderlyingError=0x8c72e70
"Request failed: unacceptable content-type: text/html",
I'm not sure what the problem is. I found this question, which I thought might be a similar problem, but the answers say to either use the AFJSONRequestOperation class (which I can't because I'm using AFNetworking version 2, which doesn't have that class), or to fix it on the server side (which I also can't for obvious reasons).
What can I fix this error when I can't fix the server side and I can't use AFJSONRequestOperation?
If using AFNetworking 2.0, you can use the POST method, which simplifies this a bit:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
NSDictionary *parameters = #{#"username":username, #"password":password};
[manager POST:#"https://mycompany.atlassian.net/rest/auth/latest/session/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
This does the creation of the request, setting its Content-Type according to the requestSerializer setting, and encodes the JSON for you. One of the advantages of AFNetworking is that you can get out of the weeds of constructing and configuring NSURLRequest objects manually.
By the way, the "Request failed: unacceptable content-type: text/html" error means that regardless of what you were expecting to receive (e.g. JSON), you received HTML response. This is very common: Many server errors (e.g. the server informing you that the request was malformed, etc.) generate HTML error messages. If you want to see that HTML, in your failure block, simply log the operation.responseString.
It turns out the problem is that this one line:
[request setValue:#"application/json" forHTTPHeaderField:#"Accept" ];
Should be
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type" ];
The error is now solved. (Edit: I should have both, see CouchDeveloper's comment.)
EDIT
Rob's solution is better, so I'm going with it. I had actually tried a similar solution to what he shows, but where he had the line,
manager.requestSerializer = [AFJSONRequestSerializer serializer];
I had the line:
[manager.requestSerializer
setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
...which didn't work. Kudos to Rob for getting it to work!
I had the same problem in AFNetworking 2.0 and the solution was that I had to make sure I set the AFHTTPRequestSerializer type (In case your request is JSON) the it should be like this.
AFHTTPSessionManager *myHTTPManager = ...
[myManager setRequestSerializer:[AFJSONRequestSerializer serializer]];
You have to set both AFHTTPResponseSerializer and AFHTTPRequestSerializer
if you are using default written class AFAppDotNetAPIClient and you face this error. Must add responseSerializer. see your shared method should look like -
+ (instancetype)sharedClient {
static AFAppDotNetAPIClient *_sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]];
_sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
_sharedClient.responseSerializer = [AFHTTPResponseSerializer serializer];
});
return _sharedClient;}
Use this line of code.
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];

AFNetworking 2.0 Send Post Request with URL Parameters

How do I send a POST request with AFNetworking 2.0 with all the parameters in the URL like such:
http://www.myserver.com?api_key=something&lat=2.4&radius=100
Right now I have:
NSString* query = #"http://example.com?name=param&date=param";
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{};
[manager POST:query parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
But it's not working, I get this error back:
Error Domain=AFNetworkingErrorDomain Code=-1011 "Request failed: bad request (400)
The previous best answer was to get the backend to change and accepts parameters in the body. Thats the preferred method but sometimes some of us are stuck using backends that can't change so I offer this solution....
In the class AFURLRequestSerialization there is a property called HTTPMethodsEncodingParametersInURI and that is an NSSet that contains the http methods that are allowed to use params in the uri GET, HEAD, and DELETE by default.
You could override that and include POST as well.
in AFURLRequestSerialization.m lines 462 has an if statement that checks self.HTTPMethodsEncodingParametersInURI property contains POST. if it doesn't (as it doesn't by default), it will put the parameters in the body.
You can comment out that id statement for a quick test.
To get it to work I recommend overwriting the HTTPMethodsEncodingParametersInURI property.
when setting up your AFHTTPSessionManager it should look like this...
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:self.httpBaseUrl]];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.requestSerializer.HTTPMethodsEncodingParametersInURI = [NSSet setWithArray:#[#"POST", #"GET", #"HEAD", whatever other http methods you need here....]];
this should allow for sending a parameters in the uri of a POST. worked for me, hope it helps someone else
#import "AFNetworking.h"
...
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *params = #{#"param1": value1,
#"param2": value};
manager.responseSerializer = [AFJSONResponseSerializer serializer]; // if response JSON format
[manager POST:#"http://domain.com/backend.php" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#", responseObject);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error);
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}];
try this
I've had the same problem with you.
Other people's answers seem to be accurate.
The cause of the error is:
when you init NSUrl with parameters such as http:www.baidu.com/api?id=1&name=我,it needs you to encode your urlString with utf-8
such as :
//解决奇葩需求:请求方式为post时,url带?id=1之类。主要原因是url带中文的时候url初始化失败
URLString = [URLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
Hope to help you!
can you try this.
NSString* apiURL = #"http://example.com"
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:apiURL]];
manager.responseSerializer = [AFJSONResponseSerializer serilizer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"application/json"];
NSDictionary *parameters = #{#"name":#"John",#"date":"27/12/2013"};
AFHTTPRequestOperation *apiRequest = [manager POST:#"" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog#"response ---%#,responseObject";
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
[apiRequest start];
I was able to do this by creating the string like this:
NSString *relativeURL =[NSString
stringWithFormat:#"/reward/commit?deviceUUID=%#&rewardID=%#",[[Client
sharedInstance] deviceUUID],self.rewardID];
and then passing it as the query. I had to set the requestSerializer and responseSerializer as follows:
client.requestSerializer = [AFJSONRequestSerializer serializer];
client.responseSerializer = [AFHTTPResponseSerializer serializer];
Worked for me once I left the manager.requestSerializer property alone and let it be the default (AFHTTPRequestSerializer).
The service i was POSTing to, was seemingly expecting UTF8 encoded body parameters.

Request failed: unacceptable content-type: text/html using AFNetworking 2.0

I'm trying out the new version 2.0 of AFNetworking and I'm getting the error above. Any idea why this is happening? Here's my code:
NSURL *URL = [NSURL URLWithString:kJSONlink];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[[NSOperationQueue mainQueue] addOperation:op];
I'm using Xcode 5.0.
Also, here's the error message:
Error: Error Domain=AFNetworkingErrorDomain Code=-1016 "Request failed: unacceptable content-type: text/html" UserInfo=0xda2e670 {NSErrorFailingURLKey=kJSONlink, AFNetworkingOperationFailingURLResponseErrorKey=<NSHTTPURLResponse: 0xda35180> { URL: kJSONlink } { status code: 200, headers {
Connection = "Keep-Alive";
"Content-Encoding" = gzip;
"Content-Length" = 2898;
"Content-Type" = "text/html";
Date = "Tue, 01 Oct 2013 10:59:45 GMT";
"Keep-Alive" = "timeout=5, max=100";
Server = Apache;
Vary = "Accept-Encoding";
} }, NSLocalizedDescription=Request failed: unacceptable content-type: text/html}
I just hid the JSON using kJSONlink. This should return a JSON.
This means that your server is sending "text/html" instead of the already supported types.
My solution was to add "text/html" to acceptableContentTypes set in AFURLResponseSerialization class. Just search for "acceptableContentTypes" and add #"text/html" to the set manually.
Of course, the ideal solution is to change the type sent from the server, but for that you will have to talk with the server team.
Setting my RequestOperationManager Response Serializer to HTTPResponseSerializer fixed the issue.
Objective-C
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
Swift
manager.responseSerializer = AFHTTPResponseSerializer()
Making this change means I don't need to add acceptableContentTypes to every request I make.
I took #jaytrixz's answer/comment one step further and added "text/html" to the existing set of types. That way when they fix it on the server side to "application/json" or "text/json" I claim it'll work seamlessly.
manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
On the server side, I added:
header('Content-type: application/json');
into my .php code and this also fixed the problem.
I solve this problem from a different perspective.
I think if the server sends JSON data with Content-Type: text/html header. It doesn't mean the server guy intended to send you some html but accidentally changed to JSON. It does mean the server guy just doesn't care about what the Content-Type header is. So if the server guy doesn't care as the client side you better ignore the Content-Type header as well. To ignore the Content-Type header check in AFNetworking
manager.responseSerializer.acceptableContentTypes = nil;
In this way the AFJSONResponseSerializer (the default one) will serialize the JSON data without checking Content-Type in response header.
A simple way to enable to receive "text/plain" content type:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/plain"];
Similarly if you wish to enable "text/html" content type:
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
I tried below line as per #Andrie answer but didn't work,
op.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
so after hunting more, I did work around to get it work successfully.
Here is my code snip.
AFHTTPRequestOperationManager *operation = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:url];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
AFJSONResponseSerializer *jsonResponseSerializer = [AFJSONResponseSerializer serializer];
NSMutableSet *jsonAcceptableContentTypes = [NSMutableSet setWithSet:jsonResponseSerializer.acceptableContentTypes];
[jsonAcceptableContentTypes addObject:#"text/plain"];
jsonResponseSerializer.acceptableContentTypes = jsonAcceptableContentTypes;
operation.responseSerializer = jsonResponseSerializer;
Hope this will help someone out there.
This is the only thing that I found to work
-(void) testHTTPS {
AFSecurityPolicy *securityPolicy = [[AFSecurityPolicy alloc] init];
[securityPolicy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager setSecurityPolicy:securityPolicy];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:[NSString stringWithFormat:#"%#", HOST] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *string = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"%#", string);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
If someone is using AFHTTPSessionManager then one can do like this to solve the issue,
I subclassed AFHTTPSessionManager where I'm doing like this,
NSMutableSet *contentTypes = [[NSMutableSet alloc] initWithSet:self.responseSerializer.acceptableContentTypes];
[contentTypes addObject:#"text/html"];
self.responseSerializer.acceptableContentTypes = contentTypes;
In my case, I don't have control over server setting, but I know it's expecting "application/json" for "Content-Type". I did this on the iOS client side:
manager.requestSerializer = [AFJSONRequestSerializer serializer];
refer to
AFNetworking version 2 content-type error
Just add this line :
operation.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
A good question always have multiple answers, to reduce and help you choose the right answer, here I am adding my own too. I have tested it and it works fine.
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:#"http://www.yourdomain.com/appname/data/ws/index.php/user/login/"]];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:#"POST" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *json = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(#"%#", json);
//Now convert json string to dictionary.
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"%#", error.localizedDescription);
}];
I had a somehow similar problem working with AFNetworking from a Swift codebase so I'm just leaving this here in the remote case someone is as unlucky as me having to work in such a setup. If you are, I feel you buddy, stay strong!
The operation was failing due to "unacceptable content-type", despite me actually setting the acceptableContentTypes with a Set containing the content type value in question.
The solution for me was to tweak the Swift code to be more Objective-C friendly, I guess:
serializer.acceptableContentTypes = NSSet(array: ["application/xml", "text/xml", "text/plain"]) as Set<NSObject>
UIImage *image = [UIImage imageNamed:#"decline_clicked.png"];
NSData *imageData = UIImageJPEGRepresentation(image,1);
NSString *queryStringss = [NSString stringWithFormat:#"http://119.9.77.121/lets_chat/index.php/webservices/uploadfile/"];
queryStringss = [queryStringss stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[manager POST:queryStringss parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
[formData appendPartWithFileData:imageData name:#"fileName" fileName:#"decline_clicked.png" mimeType:#"image/jpeg"];
}
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSDictionary *dict = [responseObject objectForKey:#"Result"];
NSLog(#"Success: %# ***** %#", operation.responseString, responseObject);
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
NSLog(#"Error: %# ***** %#", operation.responseString, error);
}];

Resources