AFNetworking 500响应机构

我一直在我的应用程序中使用AFNetworking 2.0。 我注意到,如果我的Web服务返回一个500状态码,我没有得到响应的主体。

这里是我的PHP代码的一个例子

try { $conn = new PDO( "sqlsrv:server=$serverName;Database = $database", $uid, $pwd); $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); return $conn; } catch( PDOException $e ) { $response->status(500); echo( "Connection Error: " . $e->getMessage() ); } 

如果我使用一个简单的rest客户端,这是一个响应主体的例子。

 Connection Error: SQLSTATE[08001]: [Microsoft][SQL Server Native Client 11.0]SQL Server Network Interfaces: Error Locating Server/Instance Specified [xFFFFFFFF]. 

但是,这似乎是我能从AFNetworking得到的唯一答复

 Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn't be completed. (Cocoa error 3840.)" (JSON text did not start with array or object and option to allow fragments not set.) UserInfo=0x15e58fa0 {NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.} 

这是我的Objective-C代码的一部分。

 ...} failure:^(NSURLSessionDataTask *task, NSError *error) { NSLog(@"%@",error.description); }]; 

有没有一种方法可以得到响应体?

编辑:更多的澄清代码

下面是我的AFHTTPSessionManager的子类的一部分

 @implementation MSMAMobileAPIClient + (MSMAMobileAPIClient *)sharedClient { static MSMAMobileAPIClient *_sharedClient = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedClient = [[MSMAMobileAPIClient alloc] initWithDefaultURL]; }); return _sharedClient; } - (id)initWithDefaultURL { return [self initWithBaseURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://%@/mamobile/index.php/" ,[[NSUserDefaults standardUserDefaults] stringForKey:@"serviceIPAddress"]]]]; } - (id)initWithBaseURL:(NSURL *)url { self = [super initWithBaseURL:url]; if (!self) { return nil; } self.responseSerializer = [AFCompoundResponseSerializer compoundSerializerWithResponseSerializers:@[[AFJSONResponseSerializer serializer], [AFHTTPResponseSerializer serializer]]]; return self; } 

我尝试将响应序列化器设置为AFCompoundResponseSerializer,但似乎没有什么区别

下面是我称之为图书pipe理员的一个子类的例子。

 -(void)searchForItemWithString:(NSString *)searchString withCompletionBlock:(arrayBlock)block { self.inventorySearchBlock = block; NSDictionary *parameters = @{@"query": searchString}; [[MSMAMobileAPIClient sharedClient] GET:@"inventory/search" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) { if (!responseObject) { NSLog(@"Error parsing JSON"); } else { //do stuff with the json dictionary that's returned.. } } failure:^(NSURLSessionDataTask *task, NSError *error) { NSLog(@"Error: %@",error.description); }]; } 

更新:我创build了一个github存储库,以包含我正在使用的最新代码。 所有的更改将在那里发布。 https://github.com/Hackmodford/HMFJSONResponseSerializerWithData

答案来自github上的这个问题。 https://github.com/AFNetworking/AFNetworking/issues/1397

gfiumara是提出这个的开发者。 我只稍微修改了他的AFJSONResponseSerializer的子类,以包含一个实际的string,而不是NSData

 //MSJSONResponseSerializerWithData.h #import "AFURLResponseSerialization.h" /// NSError userInfo key that will contain response data static NSString * const JSONResponseSerializerWithDataKey = @"JSONResponseSerializerWithDataKey"; @interface MSJSONResponseSerializerWithData : AFJSONResponseSerializer @end 

 // MSJSONResponseSerializerWithData.m #import "MSJSONResponseSerializerWithData.h" @implementation MSJSONResponseSerializerWithData - (id)responseObjectForResponse:(NSURLResponse *)response data:(NSData *)data error:(NSError *__autoreleasing *)error { if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) { if (*error != nil) { NSMutableDictionary *userInfo = [(*error).userInfo mutableCopy]; userInfo[JSONResponseSerializerWithDataKey] = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSError *newError = [NSError errorWithDomain:(*error).domain code:(*error).code userInfo:userInfo]; (*error) = newError; } return (nil); } return ([super responseObjectForResponse:response data:data error:error]); } @end 

这里是我如何在故障块中使用它的一个例子。

 } failure:^(NSURLSessionDataTask *task, NSError *error) { NSLog(@"%@",[error.userInfo objectForKey:@"JSONResponseSerializerWithDataKey"]); }]; 

您需要使用AFCompoundSerializer来告诉AFNetworking框架如何处理它可能收到的所有可能的响应。 默认情况下,它只会尝试映射JSON。 一个复合串行器将通过串行器,直到find一个不会引发错误。


你想使用:

 + (instancetype)compoundSerializerWithResponseSerializers:(NSArray *)responseSerializers 

AFCompoundResponseSerializer (在AFURLResponseSerialization.h )。

您需要传递一个可以处理响应的序列化程序。 数组中的一个序列化程序应该是AFHTTPResponseSerializer一个实例来处理你的错误响应。

如果您将我的类别包含在您的项目中,则如下所示:

 [mySessionManager POST:@"some-api" parameters:params success:^(NSURLSessionDataTask *task, NSDictionary *responseObject) { ... } failure:^(NSURLSessionDataTask *task, NSError *error) { id responseObject = error.userInfo[kErrorResponseObjectKey]; ... do something with the response ... }]; 

这是我的类别的代码。 它调整AFURLSessionManager注入完成处理程序中的垫片。 Shim将响应放入NSError的userInfo中。

https://gist.github.com/chrishulbert/35ecbec4b37d36b0d608