Swift send parameters in Alamofire - php

I want to send two values in the request:
1) operation string
2) user object
I am getting message Operation is not set even though I included in parameters "operation": "register"
I am new to Alamofire. Can anyone explain to me:
1) how to send values in the request?
2) how to send the user object?
3) how to deal with both results .Success and .Failure
Swift Code:
let urlString = URLFactory()
let url = URL(string: urlString.getAppURL())!
print("Log url: \(url)")
let user = User()
user.setEmail(email: email)
let parameters: Parameters = ["operation": "register", "user": user]
Alamofire.request(url, method: .post, parameters: parameters).responseJSON { response in
print("Log \(response)")
print("Log response.request: \(response.request)")
print("Log response.error: \(response.error)")
print("Log response.data: \(response.data)")
print("Log response.result: \(response.result)")
}
Swift Output:
Log url: http://192.168.0.101/GeolocationNews/NewsDataCrawler/app.php
Log SUCCESS: {
message = "Invalid Parameters";
result = failure;
}
Log response.request: Optional(http://192.168.0.101/GeolocationNews/NewsDataCrawler/app.php)
Log response.error: nil
Log response.data: Optional(51 bytes)
Log response.result: SUCCESS
PHP Code:
$login = new Login();
$fun = new FunctionsValidation();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$data = json_decode(file_get_contents("php://input"));
if(isset($data->operation)) {
$operation = $data->operation;
if(!empty($operation)) {
if($operation == 'register') {
echo $login->register($data);
}
} else { // if operation is empty
$response["result"] = "failure";
$response["message"] = "Operation is empty";
echo json_encode($response);
}
} else { // if operation is not set
$response["result"] = "failure";
$response["message"] = "Operation is not set";
echo json_encode($response);
}
}
UPDATE
I have tested the API by Postman sending:
{
"operation": "register",
"user":
{
"email": "email value"
}
}
It gives me: {"result":"failure","message":"Invalid Email"} so the API is working good!
I have tried sending Alamofire request with just operation in the parameters and it works. So it seems like the problem is in converting the user object to dictionary. Can anyone give me an example of how to do that?
User object:
class User: NSObject {
private var name: String,
email: String,
password: String,
oldPassword: String,
newPassword: String,
code: String
private var id: Int
override init() {
self.name = ""
self.email = ""
self.password = ""
self.oldPassword = ""
self.newPassword = ""
self.code = ""
self.id = 0
}
// set and get methods ...
}

I think the problem is with encoding. As per your PHP code it accepts application/json as a content type and this should be sent through Almofire with JSON encoding.
Try this instead:
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
print("Log \(response)")
print("Log response.request: \(response.request)")
print("Log response.error: \(response.error)")
print("Log response.data: \(response.data)")
print("Log response.result: \(response.result)")
}
Reference:
https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#parameter-encoding

The problem was with converting the user object to a dictionary. Instead of using an object, I just set the user as a dictionary.
let userDictionary: Dictionary = ["email": email, "password": password]
let parameters: Parameters = ["operation": operation, "user": userDictionary]
Alamofire.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseJSON { response in
...
}

Related

I not able to decode JSON data in swift

I am trying to create simple login and signup in swift with php mysql in backend. I was following "https://github.com/EMacco/ios-tutorials/tree/yummie-network-connection/Yummie" this project
I get the following error
The response is: {"data":[{"response":"Success","username":"Mohammad Tariq Shamim"}]} Error Response could not be decoded
I am getting response from the server but JSON is not getting decoded. Following is my code
enum Route {
static let baseurl = "http://arabscholar.net/android/"
case login
var description: String {
switch self {
case .login: return "login.php"
}
}
}
struct User: Decodable{ let username: String? let response: String? }
struct ApiResponse<T: Decodable>: Decodable {
let status: Int
let data: T?
let error: String?
}
AppError Swift file
enum AppError: LocalizedError {
case errorDecoding
case unknownError
case invalidUrl
case serverError(String)
var errorDescription: String? {
switch self {
case .errorDecoding:
return "Response could not be decoded"
case .unknownError:
return "Unknown error"
case .invalidUrl:
return "Url invalid"
case .serverError(let error):
return error
}
}
}
Main networking struct file
struct NetworkService {
static let shared = NetworkService()
private init() {}
func signin(username: String, password: String, completion: #escaping(Result<User, Error>) -> Void) {
let params = ["login": "user", "email": username, "password": password]
request(route: .login, method: .post, parameters: params, completion: completion)
}
private func request<T: Decodable>(route: Route, method: Method, parameters: [String: Any]? = nil, completion: #escaping(Result<T, Error>) -> Void) {
guard let request = createRequest(route: route, method: method, parameters: parameters) else {
completion(.failure(AppError.unknownError))
return
}
URLSession.shared.dataTask(with: request) { data, response, error in
var result: Result<Data, Error>?
if let data = data {
result = .success(data)
let responseString = String(data: data, encoding: .utf8) ?? "Could not stringify our data"
print("The response is: (responseString)")
} else if let error = error {
result = .failure(error)
print("The error is " + error.localizedDescription)
}
DispatchQueue.main.async {
self.handleResponse(result: result, completion: completion)
}
}.resume()
}
private func handleResponse<T: Decodable>(result: Result<Data, Error>?, completion: (Result<T, Error>) -> Void) {
guard let result = result else {
completion(.failure(AppError.unknownError))
return
}
switch result {
case .success(let data):
let decoder = JSONDecoder()
guard let response = try? decoder.decode(ApiResponse.self, from: data) else {
completion(.failure(AppError.errorDecoding))
return
}
if let error = response.error {
completion(.failure(AppError.serverError(error)))
return
}
if let decodedData = response.data {
completion(.success(decodedData))
} else {
completion(.failure(AppError.unknownError))
}
case .failure(let error):
completion(.failure(error))
}
}
private func createRequest(route: Route, method: Method, parameters: [String: Any]? = nil) -> URLRequest? {
let urlString = Route.baseurl + route.description
guard let url = urlString.asUrl else {return nil}
var urlRequest = URLRequest(url: url)
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = method.rawValue
if let params = parameters {
switch method {
case .get:
var urlComponent = URLComponents(string: urlString)
urlComponent?.queryItems = params.map { URLQueryItem(name: $0, value: "($1)")}
urlRequest.url = urlComponent?.url
case .post:
let bodyData = try?JSONSerialization.data(withJSONObject: params, options: [])
urlRequest.httpBody = bodyData
}
}
return urlRequest
}
}
My PHP code
$postdata = json_decode( file_get_contents( "php://input" ), TRUE );
//$id = $postdata[ "email" ];
//$name = $postdata[ "password" ];
$result[ 'response' ] = "Success";
$result[ 'username' ] = "Mohammad Tariq Shamim";
// Store values in an array
$returnValue = array( $result );
$array['data'] = $returnValue;
// Send back request in JSON format
echo json_encode( $array );
//echo json_encode( array( 'response' => 'No data found for ' . $_POST[ 'email' ] ) );

I get error while I send three array post with Alamofire in database?

This is my php code. I need to send here 3 parameters like cammand , mobile and token. include "../db.php";
//$_POST['command'] ;//
$command = $_POST['command'];
if ($command == "register_user") {//register user
$mobile = $_POST['mobile'];
$token = $_POST['token'];
$sql = "SELECT * FROM tbl_user where mobile ={$mobile}";
$result = mysqli_query($connection, $sql);
$num = mysqli_num_rows($result);
This my swift code.
import Foundation
import UIKit
import Alamofire
class LoginViewController: UIViewController {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
#IBOutlet weak var inputTelephoneNumber: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func loginBtn(_ sender: Any) {
let Parametrs : Parameters = [
"command": "register_user",
"mobile": inputTelephoneNumber.text!,
"token": appDelegate.myToken!
]
AF.request("http://192.xxxxxxxxx/xxxxxxxx/api/sms_verify.php", method: .post, parameters: Parametrs, encoding: JSONEncoding.default)
.responseJSON { response in
print(response)
}
let tokenURL = "http://192xxxxxx/xxxxxxxxx/api/sms_verify.php"
if let url = URL(string: tokenURL) {
let task = URLSession.shared.dataTask(with: url) {
data, response, error in
if error != nil {
print(error!)
} else {
if let responseString = String(data: data!, encoding: .utf8) {
print(responseString)
}
}
}
task.resume()
}
}
}
I get this error from xcode.
<br />
<b>Notice</b>: Undefined index: command in <b>/opt/lampp/htdocs/foroshgah1/api/sms_verify.php</b> on line <b>5</b><br />
failure(Alamofire.AFError.responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.jsonSerializationFailed(error: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.})))
I try to send three parameters like cammand = register_user , mobile and token.
I try to send them like json encode but I did not know I correct form or no?
To pass URL encoded parameters in a post request, you need to call the request function of Alamofire passing an instance of URLEncoding as encoding parameter:
AF.request(
"http://192.xxxxxxxxx/xxxxxxxx/api/sms_verify.php",
method: .post,
parameters: Parametrs,
encoding: URLEncoding.default
).responseJSON { response in
print(response)
}

Return Json from Php to Swift Alamofire

Hi guys i am using alamofire on a swift 3 iphone program, my problem is that i need to return a value from the php page my problem is that the value that comes back to me is this. How do I make sure that the value I return is: no prova#email.it
I hope I have explained
RETURN VALUE(NOT CORRECT):
SUCCESS: {
message = "no Optional(\"prova#email.it\")";
}
no Optional("prova#email.it")
SWIFT CODE:
import Foundation
import Alamofire
class User{
//URL to our web service
var email=""
var password=""
func PrintValue(){
// print(username);
//print(password);
}
func Login() -> String{
//var ris="";
var readvalue=""
let URLString = "http://localhost/test/login_mobile.php"
let parameters_value: Parameters = [
"email": email,
"password": password
]
//Sending http post request
Alamofire.request(URLString, method: .post, parameters: parameters_value).responseJSON
{
response in
//printing response
print(response)
//getting the json value from the server
if let result = response.result.value {
//converting it as NSDictionary
let jsonData = result as! NSDictionary
//displaying the message in label
readvalue = (jsonData.value(forKey: "message") as! String?)!
print(readvalue)
}
}
return readvalue
}
}
PHP CODE:
<?php
include 'user.php';
header('Content-Type: application/json');
$email= $_POST['email'];
$password = $_POST['password'];
$ris['message']="";
$user = new User();
//procedo con il login
if($user->login($email,$password,"MOBILE")==true){
$ris['message']="yes";
}
else{
$ris['message']="no $email";
}
echo json_encode($ris);
?>
I think it can be done something like:
if let readvalue = jsonData.value(forKey: "message") as? String {
print(readvalue)
}
must print wihtout Optional
Just did this in a playground and it works as expected..
import UIKit
let response: [AnyHashable: Any] = [
"message": "hello world"
]
class MyCoolClass {
func login() {
var readvalue = ""
let jsonData = response as NSDictionary
readvalue = jsonData.value(forKey: "message") as! String
debugPrint("the readvalue is: \(readvalue)")
}
}
let instance = MyCoolClass()
instance.login()
This will print: "the readvalue is: hello world"
The code is not very failsafe...
You need to use nil coalescing to make your value non-optional. e.g. print(readvalue ?? "nil"). Something better would be reengineer your response handling to properly return a typed value or a specific error.

POST Request with JSON dictionary does not return correct value with $_POST in Swift 3?

I'm trying to do is submit the device IMEI to be inserted into the database.
However, the returned JSON output from the database shows the IMEI as null.
Here's what's been implemented:
Requester
class Requester
{
....
func postRequest(_ url: URL, headers : Dictionary<String,String>?, data: Data?, callback : #escaping (_ response: HTTPResponseWithData) -> Void) -> Void
{
let request = Factory.httpRequest(url, method: "POST", headers: headers, data: data)
let task = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: {
data, response, error in
print("RESPONSE: \(response)");
})
task.resume()
}
....
}
Factory
class Factory
{
func httpRequest(_ url: URL, method: String, headers: Dictionary<String, String>?, data: Data?) -> URLRequest
{
var request = URLRequest(url: url)
request.httpMethod = method
if headers != nil
{
for (field, value) in headers!
{
request.addValue(value, forHTTPHeaderField: field)
}
}
if data != nil
{
request.httpBody = data
}
return request
}
}
MainVC
let requester = Requester()
#IBAction func sendRequest(_ sender: Any)
{
var json: Dictionary<String, Any> = [:]
json["imei"] = myIMEI
do
{
let data = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
post(theData: data)
}
catch let error as NSError
{
print(error.localizedDescription)
}
}
func post(theData: Data) -> Void
{
self.requester.postRequest("www.url.com", headers: nil, data: theData, callback: {(response: HTTPResponseWithData) -> Void in
if response.statusCode == 200 && response.data != nil && HTTPHeader.isContentTypeJSON(response.mimeType)
{
print(response.data!)
do
{
if let test = try JSONSerialization.jsonObject(with: response.data!, options: JSONSerialization.ReadingOptions()) as? Dictionary<String, Any>
{
print("test = \(test)")
}
}
catch
{
print("ERROR parsing data")
}
}
else
{
}
});
}
What I get back from the output is:
test = ["imei": <null>]
I've looked at numerous questions and answers on SO regarding this, and besides my implementation being in different classes, I don't see what could possibly be wrong.
Here's some snippet of the PHP code:
header("Content-Type: application/json");
$imei = $_POST["imei"];
$something_else = $_POST["something_else"];
$mysqli = new mysqli($host, $userid, $password, $database);
if ($mysqli->connect_errno)
{
echo json_encode(array("success" => false, "message" => $mysqli->connect_error, "sqlerrno" => $mysqli->connect_errno));
exit();
}
echo json_encode( array('imei'=>$imei) );
What exactly is wrong with my POST request implementation that is not allowing me to submit the IMEI to the database?
If it helps, the RESPONSE output is:
RESPONSE: Optional( { URL:
http://www.url.com } { status code: 200, headers {
Connection = "Keep-Alive";
"Content-Type" = "application/json";
Date = "Mon, 02 Jan 2017 08:07:54 GMT";
"Keep-Alive" = "timeout=2, max=96";
Server = Apache;
"Transfer-Encoding" = Identity; } })
UPDATE: After further testing, I replaced the above php code after the header with the following code, and now the imei is reported:
$handle = fopen("php://input", "rb");
$raw_post_data = '';
while (!feof($handle))
{
$raw_post_data .= fread($handle, 8192);
}
fclose($handle);
$request_data = json_decode($raw_post_data, true);
$imei = $request_data["imei"];
I'm confused, why is it the case that the updated php code works but the one involving $_POST does not?
See the $_POST documentation which says it is:
An associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.
But you're not doing x-www-form-urlencoded request. You're performing an application/json request. So you can't use $_POST. Use php://input (e.g., as discussed here: iOS Send JSON data in POST request using NSJSONSerialization).

Alamofire Error: Data couldn't be read because it isn't in the correct format

I receive an error when trying to send parameters via POST request to my server via Alamofire.
// Create payload to be submitted to the server
let userReference = appDelegate.userReference
let parameters : [String : AnyObject] = [
"userReference": userReference,
"pushToken": pushToken,
"installationReference": ""
]
Server().sendPOSTRequestToServer(endpoint: "devices", parameters: parameters) { (response) -> Void in
let responseCode = response["code"]
switch(responseCode) {
case 201:
completionHandler(response: response)
break
default:
break
}
}
}
func sendPOSTRequestToServer(endpoint endpoint: String, parameters: [String:AnyObject], completionHandler: (response: JSON) -> Void) {
Alamofire.request(.POST, self.requestUrl + endpoint, parameters: parameters, encoding: .JSON).responseJSON { (response) -> Void in
switch response.result {
case .Success:
completionHandler(response: JSON(response.result.value!))
case .Failure(let error):
print("POST REQUEST ERROR - \(endpoint) - \(error.localizedDescription)")
print("=== REQUEST INFORMATION ===")
print("Status Code: \(response.response!.statusCode)")
print("Request URL: \(response.request!.URLString)")
print("Request Payload: \(parameters)")
print("===")
}
}
}
The error I receive is:
> POST REQUEST ERROR - devices - The data couldn’t be read because it
> isn’t in the correct format.
> === REQUEST INFORMATION === Status Code: 200 Request URL: http://SERVERIP/v1/devices Request Payload: ["pushToken":
> PUSHTOKEN,
> "userReference": res_hq9gpcgap09joe, "installationReference": ABC]
> ===
I formated the parameters array correctly I would guess. Where is this error coming from?
The Server code:
// Store new Device
public function store(Request $request) {
// Get payload from request
$bodyContent = json_decode($request->getContent(), true);
$installationReference = $bodyContent["installationReference"];
$devicesFound = DeviceHelper::searchForExistingDevice($installationReference);
if ($devicesFound == 0) {
// If no device is found, create unique id for device as installation id and execute command to register device.
$newInstallationReference = "ins_" . CustomHelper::createUniqueId(14);
$registerDeviceCommand = new RegisterDeviceCommand($bodyContent, $newInstallationReference);
$this->commandBus->execute($registerDeviceCommand);
$this->respondCreated("Device was created.");
return json_encode(array("code" => $this->statusCode, "installationReference" => $newInstallationReference), JSON_NUMERIC_CHECK);
} else {
$this->setStatusCode(404)->respondWithError("Device already exists");
return json_encode(array("code" => $this->statusCode), JSON_NUMERIC_CHECK);
}
}

Categories