Obj-C – Données POST JSON sur le server?

Désolé pour la nouvelle question, mais je me suis arraché les cheveux sur celui-ci. Je peux envoyer des données POST avec succès à mon URL de sharepoint terminaison via un programme comme POSTER de FireFox. Cependant, j'essaie de publier ces mêmes données JSON depuis mon application vers mon URL de sharepoint terminaison (sharepoint terminaison push_notifications des services Drupal), et pour une raison quelconque, cela ne sera pas POST réussi. Voici le code que j'utilise:

ViewController.m

NSSsortingng *urlSsortingng1 = @"http://app.com/endpoint001/push_notifications"; NSDictionary *jsonBodyDict = @{@"token":postDeviceID, @"type":@"ios"}; NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil]; // watch out: error is nil here, but you never do that in production code. Do proper checks! NSSsortingng *urlSsortingng2 = [NSSsortingng ssortingngWithFormat:@"http://app.com/endpoint001/push_notifications?token=%@&type=%@", postDeviceID,@"ios"]; NSMutableURLRequest *request = [NSMutableURLRequest new]; request.HTTPMethod = @"POST"; // for alternative 1: [request setURL:[NSURL URLWithSsortingng:urlSsortingng1]]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setHTTPBody:jsonBodyData]; [request addValue:csrfToken forHTTPHeaderField:@"X-CSRF-Token"]; // for alternative 2: [request setURL:[NSURL URLWithSsortingng:urlSsortingng2]]; // no body needed, though that ultimately depends on your server. Also, I didn't test this for lack of a backend :) NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"Yay, done! Check for errors in response!"); NSHTTPURLResponse *asHTTPResponse = (NSHTTPURLResponse *) response; NSLog(@"The response is: %@", asHTTPResponse); // set a breakpoint on the last NSLog and investigate the response in the debugger // if you get data, you can inspect that, too. If it's JSON, do one of these: NSDictionary *forJSONObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; // or NSArray *forJSONArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; NSLog(@"One of these might exist - object: %@ \n array: %@", forJSONObject, forJSONArray); }]; [task resume]; 

Remarque: J'ai mis ce code dans AFTER mon user se connecte avec succès, donc je ne suis pas sûr de commencer une nouvelle connection est nécessaire? Comment puis-je POSTER mes données sur le server si une session et un jeton CSRF existent déjà? À quoi devrait ressembler mon code? Celui qui répond à cette question va sur ma list de Noël … O_O

Réponse de NSLog:

 2017-07-17 17:31:11.421281-0700 app[977:206852] Yay, done! Check for errors in response! 2017-07-17 17:31:11.422198-0700 app[977:206852] The response is: <NSHTTPURLResponse: 0x170239b40> { URL: http://app.com/endpoint001/push_notifications?token=9526687d594944513b0wabf704eae3223f0de9bf69136a0aae3ab046863474b1&type=ios } { status code: 401, headers { "Cache-Control" = "no-cache, must-revalidate"; Connection = "keep-alive"; "Content-Type" = "application/json"; Date = "Tue, 18 Jul 2017 00:14:35 GMT"; Expires = "Sun, 19 Nov 1978 05:00:00 GMT"; Server = Apache; "Transfer-Encoding" = Identity; Vary = Accept; "X-Content-Type-Options" = nosniff; } } 2017-07-17 17:31:27.172085-0700 app[977:207024] XPC connection interrupted 2017-07-17 17:31:27.172311-0700 app[977:206852] One of these might exist - object: ( "CSRF validation failed" ) array: ( "CSRF validation failed" ) 

La réponse de Tom donne la bonne direction, mais je vois que le manque de description de ce que le code fait est source de confusion pour vous. En outre, vous utilisez des methods obsolètes (de NSURLConnection ), donc j'ai fait un exemple rapide (non testé) en utilisant NSURLSession et ses classs liées. Ne vous inquiétez pas, c'est fondamentalement la même chose.

Cela étant dit, la façon dont vous essayez ceci dans votre code original me fait me requestr si vous envoyez réellement un corps json (c'est-à-dire votre backend l'attend) ou plutôt le système repose sur des parameters ennuyeux pour l'URL. J'ai donc ajouté les deux façons dans mon code:

 NSSsortingng *postDeviceID = @"something"; NSSsortingng *urlSsortingng1 = @"http://myurl.com/endpoint01/push_notifications"; NSDictionary *jsonBodyDict = @{@"token":postDeviceID, @"type":@"ios"}; NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil]; // watch out: error is nil here, but you never do that in production code. Do proper checks! NSSsortingng *urlSsortingng2 = [NSSsortingng ssortingngWithFormat:@"http://myurl.com/endpoint01/push_notifications?token=%@&type=%@", postDeviceID,@"ios"]; NSMutableURLRequest *request = [NSMutableURLRequest new]; request.HTTPMethod = @"POST"; // for alternative 1: [request setURL:[NSURL URLWithSsortingng:urlSsortingng1]]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setHTTPBody:jsonBodyData]; // for alternative 2: [request setURL:[NSURL URLWithSsortingng:urlSsortingng2]]; // no body needed, though that ultimately depends on your server. Also, I didn't test this for lack of a backend :) NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"Yay, done! Check for errors in response!"); NSHTTPURLResponse *asHTTPResponse = (NSHTTPURLResponse *) response; NSLog(@"The response is: %@", asHTTPResponse); // set a breakpoint on the last NSLog and investigate the response in the debugger // if you get data, you can inspect that, too. If it's JSON, do one of these: NSDictionary *forJSONObject = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; // or NSArray *forJSONArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; NSLog(@"One of these might exist - object: %@ \n array: %@", forJSONObject, forJSONArray); }]; [task resume]; 

Il est également possible que votre système prenne en charge les deux manières, mais apprendre à build un bon corps JSON est toujours utile. Notez que la raison pour laquelle le code de Tom vous fait penser qu'il est affiché est que vous semblez mal comprendre comment fonctionne NSURLConnection (sauf si vous avez exclu du code): L'object est toujours construit comme vous l'utilisez, donc if (conn) est toujours dans la twig YES . Cela ne signifie pas la connection, c'est-à-dire que le chargement réel réussit. L'initialiseur renvoie nil s'il ne peut pas créer une instance, pas si une instance valide s'appuie simplement sur des données refusées lors de la connection à sa cible. Vous n'obtenez pas d'erreur pour cela de cette façon (vous devez utiliser la délégation pour cela).

L'approche de session que j'ai montrée vous donne un bloc d'achèvement dans lequel vous pouvez examiner ce que le server répond pour localiser plus loin ce qui s'est mal passé. Vous pouvez simplement définir un point d'arrêt et regarder l'erreur (qui est nil si elle réussit), l'état dans la réponse, etc.

Je n'ai évidemment pas exécuté ce code exact, donc excusez toutes les fautes de frappe, mais j'ai utilisé cette approche beaucoup avec le chargement et l'envoi à une variété de backends pour mon travail habituel. En général, cela devrait fonctionner (et, plus important encore, vous permettre de comprendre ce que votre backend attend, en supposant que vous n'avez pas de document détaillé à ce sujet).


Editer :

D'accord, cet indice dans le commentaire de code était peut-être trompeur: je voulais vérifier la réponse pour les erreurs. L'object response (voir aussi la documentation de la méthode dataTask... en général). J'ai ajouté du code en y consortingbuant un peu, mais sachez que la conversion de l'object de data en JSON dépend de ce que votre server peut réellement transmettre. Ou il pourrait avoir un format bizarre ou quelque chose, vous devez comprendre cela. Pour les choses simples qui sont POSTed, il peut ne pas fournir de données, vous obtenez simplement une information sur si cela a fonctionné ou non dans la response . Notez en particulier la propriété statusCode . À less que votre server ne fasse quelque chose de bizarre, c'est le code d'état HTTP défini par la norme et devrait vous aider. Si, par exemple, la façon dont vous avez construit votre corps dans la requête (le jsonBodyDict dans mon exemple de code) était erronée (mauvais noms d'éléments ou autres), vous obtiendriez un 400.

En général, vous devez comprendre que la signification de "erreur" n'est pas si simple ici. Les methods considèrent ne pas pouvoir se connecter du tout comme une erreur, donc vous obtenez un object d'erreur dans le bloc d'achèvement dans ces cas. C'est généralement le cas lorsque votre server n'existe tout simplement pas. Si, toutefois, vous ne parvenez pas à communiquer les informations souhaitées à votre server, ce n'est pas une erreur du sharepoint vue de l'API et vous ne recevez pas d'object d'erreur. Vous obtenez une réponse valide qui dit "cette request était erronée". Vous faites déjà du bien dans votre cas, car la connection semble se produire et fonctionne, vous n'envoyez pas encore datatables attendues par votre server. La response devrait donner plus d'informations à ce sujet.

Déboguer davantage cela irait au-delà de la scope de cette question, car finalement nous parlons de la façon dont votre backend spécifique se comporte maintenant. Si vous ne pouvez pas comprendre cela, vous devez me donner les informations d'identification pour votre server afin que je puisse le tester moi-même, tout le rest devinerait de ma part maintenant. 🙂 Nous pouvons le faire, mais il est probablement préférable de le faire dans le chat et non dans une question / réponse qui est déjà longue, hehe.

Toutes les réponses sont bonnes mais je post une méthode, pour la mise en œuvre correcte de l'envoi de données JSON à l' POST API

Méthode POST

  -(void)postServiceAPI:(NSSsortingng*)url andParameters:(NSSsortingng *)parameterSsortingng andCompletionHandler:(void(^)(NSData *data,NSError *error,BOOL networkError))compilationHandler { // Checking the Network availability : You can skip this check Reachability *netConnectionReach = [Reachability reachabilityWithHostname:@"www.google.com"]; NetworkStatus internetStatus = [netConnectionReach currentReachabilityStatus]; if ((internetStatus != ReachableViaWiFi) && (internetStatus != ReachableViaWWAN)) { dispatch_async(dispatch_get_main_queue(), ^{ compilationHandler(nil,nil,TRUE); }); } else { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; configuration.timeoutIntervalForRequest = 30.0; configuration.timeoutIntervalForResource = 60.0; configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData; _session = [NSURLSession sessionWithConfiguration:configuration]; NSURL *urlStr = [NSURL URLWithSsortingng:url]; NSData *postData = [parameterSsortingng dataUsingEncoding:NSASCIISsortingngEncoding allowLossyConversion:YES]; NSSsortingng *postLength = [NSSsortingng ssortingngWithFormat:@"%lu",(unsigned long)[postData length]]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlStr cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0]; [request setHTTPMethod:@"POST"]; [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; // You can also set " application/json" // This will solve your problem [ request setValue:@"Your_Token" forHTTPHeaderField:@"your_key_for_token"]; [request setHTTPBody:postData]; [[_session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { dispatch_async(dispatch_get_main_queue(), ^{ compilationHandler(nil,error,nil); }); } else { dispatch_async(dispatch_get_main_queue(), ^{ compilationHandler(data,nil,nil); }); } }]resume]; } } 

Les usages:

  NSMutableDictionary *dict = [[NSMutableDictionary alloc]init]; [dict setObject:postDeviceID forKey:@"token"]; [dict setObject:@"iOS" forKey:@"type"]; NSData * JsonData =[NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil]; NSSsortingng *urlStr = @"http://myurl.com/endpoint01/push_notifications" NSSsortingng *parameterJsonSsortingng= [[NSSsortingng alloc] initWithData:JsonData encoding:NSUTF8SsortingngEncoding]; // If you Don't want to create Dictionary than just send your Parameter JSon what you have made , please make sure if json is correct or not //parameterJsonSsortingng = [NSSsortingng ssortingngWithFormat:@"token=%@&type=%@",postDeviceID,@"ios"]; NSLog(@"URL:%@ Request :\n\n %@",urlStr,parameterJsonSsortingng); [self postServiceAPI:urlStr andParameters:parameterJsonSsortingng andCompletionHandler:^(NSData *data, NSError *error, BOOL networkError) { // If Data Retrun By API is not nil if (data) { // Here is your Response NSDictionary *dicData=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; } else { // Show Alert When data is Not Recived from API if (networkError) { // No Internet Connection } else { // Network Error NSLog(@"Network Error : %@",error.description); } } }]; 

J'espère que cela t'aidera

 //Generate your postData NSDictionary *postDict = @{@"token":postDeviceID, @"type":@"ios"}; //convert object to data NSError *error; NSData *postData = [NSJSONSerialization dataWithJSONObject:postDict options:kNilOptions error:&error]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setHTTPMethod:@"POST"]; [request setURL:[NSURL URLWithSsortingng:@"http://myurl.com/endpoint01/push_notifications"]]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setHTTPBody:postData]; NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self]; if(conn) { NSLog(@"Connection Successful"); } else { NSLog(@"Connection could not be made"); } 

Est-ce que vos données JSON doivent être sous la forme de Ssortingng ou Dictionary comme dit par tom

NSSsortingng *post = [NSSsortingng ssortingngWithFormat:@"token=%@&type=%@",postDeviceID,@"ios"]; – Est-ce correct?

Si oui.

Pouvez-vous vérifier avec la requête asynchronous en utilisant NSURLConnection au lieu des methods de délégué.

 NSSsortingng *post = [NSSsortingng ssortingngWithFormat:@"token=%@&type=%@",postDeviceID,@"ios"]; NSData *postData = [post dataUsingEncoding:NSASCIISsortingngEncoding allowLossyConversion:YES]; NSSsortingng *postLength = [NSSsortingng ssortingngWithFormat:@"%lu",(unsigned long)[postData length]]; NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init]; [request setHTTPMethod:@"POST"]; [request setValue:postLength forHTTPHeaderField:@"Content-Length"]; [request setURL:[NSURL URLWithSsortingng:@"http://myurl.com/endpoint01/push_notifications"]]; [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:postData]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { if(data!=nil) { id res =[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; } }]; 

J'espère que cela aide.