Pass an array to .net webservice in ios sdk - ios

I like to call the json web service through my iphone app.
I try to pass the array like as follow:
NSArray *keys = [NSArray arrayWithObjects:#"key",nil];
NSArray *objects = [NSArray arrayWithObjects:venueId,nil];
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSString* jsonString = [jsonDictionary JSONRepresentation];
NSLog(#"%#",jsonString);
Call to webservice
SBJSON *json = [SBJSON new];
json.humanReadable = YES;
responseData = [[NSMutableData data] retain];
NSString *service = #"/DerializeDataTable";
NSString *requestString = [NSString stringWithFormat:#"{\"n\":\"%#\"}",jsonString];
NSLog(#"request string:%#",requestString);
Requsted String
{"n":"{"key":["4e78b7f7483bc8fe83ed2bf9","4de248a21520b8ceaabd9197","4f0d502be4b0dd89303e6bde","4f2a79a1e4b0b052a3f37633","500ebf52e4b0edbb8dbc7e9c","4d63a047a45b5481c872032d"]}"}
But can't able to get the response.
I don't know what is the reason.
I don't know the any problem on my side or server side.

You haven't posted the code where you actually send the request off to your web service, so it is going to be hard to help you.
The first thing you should do is isolate whether the problem is with your client (the app) or your server. You can do this by logging the response you get when you send the message - it sounds as if you're getting no response, in which case you might be better off examining your server logs to see if the request ever reaches your server. You might find it useful to use a proxy to actually see the network traffic as it leaves your app.

Looks like you have extra quotes in there. I think you mean:
{"n":{"key": ["4e78b7f7483bc8fe83ed2bf9","4de248a21520b8ceaabd9197","4f0d502be4b0dd89303e6bde","4f2a79a1e4b0b052a3f37633","500ebf52e4b0edbb8dbc7e9c","4d63a047a45b5481c872032d"]}}

Related

Why is NSJSONSerialization parsing NSDictionary incorrectly into JSON?

I'm making a POST request to a server from an IOS app and sending a JSON payload of an email and password value.
My code so far is making a NSDictionary and serializing it into NSData:
NSDictionary *dictionary = #{ #"email" : #"khush#gmail.com" , #"password" : #"mypass" };
NSData *payload = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
I attach the payload as part of the request.HTTPBody, however the server receives the following data:
{ '{"email":"khush#gmail.com", "password":"mypass"}' : ' ' }
It seems to be taking the whole string as the key and emitting a null as the value.
Any ideas/solutions to this problem? I've had a look at but it doesn't make See this link sense to me.
Nothing is wrong in your payload. Data is being messed up in HTTP layer. Please ensure you have following content type set in your request headers.
"Content-Type" = "application/json";
Seems like you are making something like
request.HTTPBody = encodedVersionOfPayload;
while you should be marking something more like
request.HTTPBody = [NSString stringWithFormat:#"%#=%#", yourKey, encodedVersionOfPayload];
Please show us this part of your code.
UPDATE
After a quick look to documentation, NSMutableURLRequest, HTTPBody property is a NSData and not a NSString,
so you have probably written
request.HTTPBody = payload;
where you should have something more like
NSString *jsonString = [[NSString alloc] initWithData:payload encoding:NSUTF8StringEncoding];
NSString *payloadString = [NSString stringWithFormat:#"data=%#", jsonString];
request.HTTPBody = [payloadString dataUsingEncoding:NSUTF8StringEncoding];
(not tested but should be correct, your json object should be available on your server using the key "data")

Getting %20 in twitter private message

Hi here is my code for sending private message to twitter follower/followings,message has been sent but problem is followers are getting message string with %20
-(void)PostOnTwitter :(NSArray *)ParamArray
{
NSLog(#"ParamArray===%#",ParamArray);
if([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
if(!accountStore)
accountStore = [[ACAccountStore alloc] init];
ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
if(granted!=0)
{
NSArray *twitterAccounts = [self.accountStore accountsWithAccountType:accountType];
NSURL *MsgUrl=[NSURL URLWithString:#"https://api.twitter.com/1.1/direct_messages/new.json"];
NSDictionary *Msgparams = #{#"screen_name" : [ParamArray objectAtIndex:0], #"text" :
[[ParamArray objectAtIndex:1]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] };
SLRequest *Msgrequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:MsgUrl parameters:Msgparams];
[Msgrequest setAccount:[twitterAccounts lastObject]];
[Msgrequest performRequestWithHandler:^(NSData *responseData,NSHTTPURLResponse *urlResponse,NSError *error) {
if (responseData) {
if (urlResponse.statusCode >= 200 && urlResponse.statusCode < 300) {
NSError *jsonError;
NSDictionary *timelineData = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:&jsonError];
if (timelineData) {
[self performSelectorOnMainThread:#selector(CardHasSent) withObject:nil waitUntilDone:NO];
}
}
}
}];
}
}];
}
}
My followers are getting private message like
user%20has%20sent%20you%20a%20card%20from%20happy%20heART%20cards.%20http://www.happyheartcards.net/o.php?t=ODYw
How can I send proper text?Please help.
I think probelm is stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding,but if I don't use NSUTF8StringEncoding message sending fails.
ParamArray has not been encoded earlier ParamArray===(
jry088,
"user has sent you a card from happy heART cards. http://www.happyheartcards.net/o.php?t=OTA1"
)
%20 is indeed the string escape for a space character, and this is the correct behaviour that you are requesting in using stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding. However, the Twitter API does want POST data for direct messages encoded like this:
https://dev.twitter.com/docs/api/1.1/post/direct_messages/new
I thought the most likely thing therefore was that you were running the encoding twice, which would mean that your % in %20s are getting re-encoded to say "Hey, I really mean a percentage sign here.
When I look at the code, there are multiple redundant calls to [ParamArray objectAtIndex:1] and earlier re-encoding of the string data into UTF8:
NSString *StringData = [ParamArray objectAtIndex:1];
const char *cString = [StringData UTF8String];
NSString *Datastringone = [NSString stringWithFormat:#"%s",cString];
NSString *str = [ParamArray objectAtIndex:1];
None of these variables or this processing ever gets used. This made me wonder whether the string in the ParamArray has already been encoded into UTF8 in an earlier part of your application, so that you are encoding it for the second time when you pass it in here.
NSDictionary *Msgparams = #{#"screen_name" : [ParamArray objectAtIndex:0], #"text" :
[[ParamArray objectAtIndex:1]stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] };
EDIT
Actually, I'm going to return to what I originally posted, before I updated the above. I think you're actually getting exactly what you ask for with that encoded text, and the question shouldn't be why you're getting %20s in your text, but rather why the code you've got now is accepting a DM whereas it was failing after all.
If you look at the API reference I linked above (https://dev.twitter.com/docs/api/1.1/post/direct_messages/new) it shows the POST data as % encoded earlier on, but if you actually look at the full code example of what is to be submitted, the string isn't actually encoded at all:
94 "text": "hello, tworld. welcome to 1.1."
So first—change as little else as possible, but remove the encoding stage, and confirm that you still can't send a DM. It could be that you fixed something else without realising it and that is why the POST started working. This would obviously be helped by not embedding the encoding stage into the creation of the dictionary. You get much more readable code if you create all the values separately and then pass the final encoded and prepared variables in when you create the dictionary. A few more temporary variables or pointers may be created but that's well worth it for the increased readability of the code. :)

JSON data in custom URL schemes

In my app, I am making a share function that sends another user an email with a URL to open my app and pass parameters. I googled around for a bit and came up with this.
I know its a terrible example, but that is all I could find. Since I need to pass a NSNumber, a NSDate, and an NSString, I figured this would be the most convenient way to do so. Right now, I cannot make sense of that code. I went ahead and got the SBJson library, which is what he appears to be using. Can someone help me out on this?
You don't have to use a library for JSON Serialization in iOS. From iOS 5.0 onwards there is a class NSJSONSerialization is available for doing this. https://developer.apple.com/library/ios/documentation/foundation/reference/nsjsonserialization_class/Reference/Reference.html
Consider this code for converting list of contacts to json string
+(NSString*) jsonStringRepresentationOfSelectedReceiptients:(NSArray*) contactsList {
NSMutableArray* contactsArray = [[NSMutableArray alloc]init];
for (ContactObject *contactObj in contactsList) {
NSDictionary* ltPair = #{#"phone_no": [NSNumber numberWithLongLong:contactObj.phoneNo, #"email_id": contactObj.emailId, #"display_name": contactObj.displayName], #"creation_date": [NSDate dateWithTimeIntervalSince1970:contactObj.timeStamp]]};
[contactsArray addObject:ltPair];
}
NSData *jsonData=[NSJSONSerialization dataWithJSONObject:contactsArray options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"json string: %#", recptJson);
return jsonString;
}
If you have proper NSDate instead of time stamp, u can directly use it.
Hope this helps.

RNCryptor not working with JSON string

Here are my method's to use RNCryptor to encrypt/decrypt a JSON string that I am sending to the web service. I am using a static IV variable which may be bad practice but please don't focus on that. Here is how I'm doing it:
Note: I'm using Matt Gallagher's NSData+Base64 category found here (at bottom of page)
-(NSString*)encryptString:(NSString*)plaintext withKey:(NSString*)key error:(NSError**)error{
NSData *data = [plaintext dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptionKey = [NSData dataFromBase64String:key];
NSData *IV = [NSData dataFromBase64String:ENCRYPTION_IV];
RNCryptorEngine *engine = [[RNCryptorEngine alloc] initWithOperation:kCCEncrypt settings:kRNCryptorAES256Settings key:encryptionKey IV:IV error:error];
[engine addData:data error:error];
NSData *encryptedData = [engine finishWithError:error];
NSString *based64Encrypted = [encryptedData base64EncodedString];
NSLog(#"Encrytped: %#", based64Encrypted);
return based64Encrypted;
}
-(NSString*) decryptString:(NSString*)cipherText withKey:(NSString*)key error:(NSError**)error;{
NSData *data = [NSData dataFromBase64String:cipherText];
NSData *encryptionKey = [NSData dataFromBase64String:key];
NSData *IV = [NSData dataFromBase64String:ENCRYPTION_IV];
RNCryptorEngine *engine = [[RNCryptorEngine alloc] initWithOperation:kCCDecrypt settings:kRNCryptorAES256Settings key:encryptionKey IV:IV error:error];
[engine addData:data error:error];
NSData *decryptedData = [engine finishWithError:error];
NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
NSLog(#"Decrypted: %#", decryptedString);
return decryptedString;
}
When I use a string like hello world it works fine. When I use a string like {"username":"developer","password":"abcdefG*12"} I imagine it hase something to do with the encoding but I really know what to use.
when I encrypt that string I get a base64 string and when I try to decrypt that I get an empty string.
UPDATE
It looks like it's failing because of the : in the json string.
What's weirder is it only fails with the string is in json format, I thought it was the : cause I tried that first but upon further investigation if I broke any of the JSON requirements ,'s {'s }'s it stopped working. It works with the RNEncryptor however so I'm not sure what I'm doing wrong. Either way, I think we may redesign the current flow
UPDATE 2
Here is where I am calling these methods:
NSDictionary *credentials = #{#"username":#"developer",#"password":#"abcdefG*12"};
NSString *jsonString = [ credentials JSONStringWithOptions:JKSerializeOptionNone error:&error];
NSLog(#"json string: %#", jsonString); //OUTPUTS: {"username":"developer","password":"abcdefG*12"}
CCGEncryption *encryptionObject = [[CCGEncryption alloc] init]; //THIS IS THE OBJECT WHERE THE encrypt/decrypt methods are
NSString *encrypted = [encryptionObject encryptString:jsonString withKey:ENCRYPTION_KEY error:&error];
if(error){
NSLog(#"Error:%#", error); //NO ERROR
}
NSString *decrypted = [encryptionObject decryptString:encrypted withKey:ENCRYPTION_KEY error:&error];
if(error){
NSLog(#"Error:%#", error); //NO ERROR
}
NSLog(#"decrypted: %#", decrypted); //OUTPUT: decrypted:
You're not collecting the data returned by addData:. The engine encrypts/decrypts as you go so that you don't have to hold the entire plaintext and ciphertext in memory. It doesn't accumulate the data unless it has to (for padding reasons). I suspect that the tests that are working are of different lengths than the ones that aren't.
You are correct that using a fixed IV is bad practice. If you use the same IV and key in multiple messages, then it is possible for attackers to recover parts of your messages by comparing the ciphertexts. If you are using AES-CBC without a random IV and an HMAC, then your AES is insecure in several ways. That is the problem RNCryptor was built to address and why the data format looks the way it does.
#jbtule is correct that I didn't particularly mean for people to use the engine directly and haven't heavily documented it, but there's no problem using it, and I can document it better to support that. That said, the engine itself is insanely simple; I just created it as a way to share code between the encryptor and decryptor. There's not much reason to use RNCryptor if you're going to bypass most of the security it provides. For the above code, it'd be a lot simpler to just call the one-shot CCCrypt().

Adding a JSON blob to a JSON request in iOS

I need to be able to create a JSON object (I'm using the built in classes in iOS 5).
The JSON that should be sent is this:
{"request_type":"<the request type (a string)>" "security_level":<the security level (an int)> "device_type":"<android or ios (a string)" "version":<the app version (android, ios on different version schemes) (a float)> "email":<the email address of the user sending the request (a string)> "blob":{<the contents of the actual request, encrypted/encoded according to the security level (a map)>}
My problem is with the last portion, a "blob"
Which is basically just another JSON object, i.e.
{"display_name":"Jack Bower", "email":"jackb#gmail.com", "password":"roflcopter"}
(Let's forget the password is in plaintext)
I can create everything using NSDictionary,
I just don't know how to add the last part.
My guess is create the first request using NSDictionary.
Then create the second blob request using another NSDictionary.
And then just add that second blob NSDictionary as a object back to the initial NSDictionary.
Will NSJSONSerialization understand what I'm trying to do?
Ok I think it's 5am and I'm just being really stupid:
here's the answer:
NSDictionary *blobData = [NSDictionary dictionaryWithObjectsAndKeys:
#"email",userEmail,
#"password",userPassword,
nil];
NSString *blobString = [[NSString alloc]
initWithData:[NSJSONSerialization dataWithJSONObject:blobData options:kNilOptions error:&error]
encoding:NSUTF8StringEncoding];
NSDictionary *requestData = [NSDictionary dictionaryWithObjectsAndKeys:
#"login",#"request_type",
0,#"security_level",
#"ios",#"device_type",
#"blob",blobString,
nil];
NSData *JSONRequestData = NULL;
if ([NSJSONSerialization isValidJSONObject:requestData]) {
NSData *JSONRequestData = [NSJSONSerialization dataWithJSONObject:requestData options:kNilOptions error:&error];
}
else NSLog(#"requestData was not a proper JSON object");

Resources