How to send data from angularjs to cakephp - angularjs

I have all my actions done in cakephp. I was using a platform in client side, and now I decided to migrate to Ionic/angularjs, but as I saw, they do not "talk" with each other. Angular uses Content-Type: application/json that cakePHP does not read with request->data or request->query.
I found some workarounds that I need to change all the actions in my server side. Is there another way to keep it without changes? I´d like to keep it working in the old client version too.
[Edited]
In algularjs I´m using $http service.

I'm not sure that I understand your problem.
If you send json data to your server with a post request, you can get data with a cakephp application easily:
jsonData = {data: [{key: 'a', value: 'b'}, {key: 'a', value: 'b'}]};
var req = {
method: 'POST',
url: 'http://example.com/Tests',
data: jsonData
}
$http(req);
Then in your controller you can get data:
class MyController extends AppController{
// ...
public function action(){
debug($this->request->data);
// you have your data from your angularjs app
// ['data' => [['key' => 'a', value => 'b'], ['key' => 'a', value => 'b']]];
}

I solved the problem changing the $http header to "application/x-www-form-urlencoded", I saw this post
body = 'cel=xxxx&pass=zczx';
var req = {
method: 'POST',
url: 'http://localhost/cakefacility/usuarios/checkUsuario.json',
data: body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
$http(req);

For Sending Data from angular to cakephp project you need to create REST API at cakephp project for creating REST API you can follow my forked github repo.
After Creating API in cakephp project you just call API like:
For Call API by GET:
$http.get("<REST API URL>").then(function(response) {
......
......
});
For Call API by POST:
$http.post(<REST API URL>, <DATA TO SEND>).success(function(data, status) {
.......
.......
});

Related

handling an angular $http request in symfony controller

i want to send data from a twig view to a symfony controller using angular js $http method
this is my javascript
<script>
var app = angular.module('app',[]);
app.controller('ctrl',function($scope,$http) {
$scope.processForm = function() {
var val = $scope.libelle;
$http({
method: "POST",
url: 'http://localhost/symangular/web/app_dev.php/home',
headers: {
'Content-Type': 'application/json'
},
data:{libelle:val}
}).then(function (html) {
console.log(html);
});
}
});
</script>
and this is my controller
class DefaultController extends Controller
{
public function indexAction(Request $request)
{
$prod = new Product();
$form = $this->createForm(ProductType::class,$prod);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid() && $request- >isMethod('POST') && $request->isXmlHttpRequest()){
$em = $this->getDoctrine()->getManager();
$data = json_decode($request->getContent(), true);
dump($request->request->get('libelle'));
$request->request->replace($data);
$prod->setLibelle($request->request->get('libelle'));
$em->persist($prod);
$em->flush();
return new JsonResponse("good");
}
return $this->render('angulartestangularBundle:Default:index.html.twig',array('form'=>$form->createView()));
}
}
so when i execute i got an object in the console that i didn't understand it also i got nothing in database , did anyone have an idea about how to handle an
$http angular request in symfony controller
Object {data: "<script src="https://ajax.googleapis.com/ajax/libs…: 5 } ); })();/*]]>*/</script>↵</body>↵", status: 200, config: Object, statusText: "OK"}
In Symfony, a request considered as a XmlHttpRequest by reading request headers. The exactly code in Symfony is:
public function isXmlHttpRequest()
{
return 'XMLHttpRequest' == $this->headers->get('X-Requested-With');
}
So, when using angularjs or any javascript framework to make a XMLHttpRequest, you should add a header with X-Requested-With key and value = XMLHttpRequest. This header also required even if you're using fetch api. In your code abow, the request call should be:
$http({
method: "POST",
url: 'http://localhost/symangular/web/app_dev.php/home',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
data:{libelle:val}
})
If you don't want to add this header every time call $http function, you can add it as default config to $httpProvider:
angular
.module('yourModuleName', [])
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}])
;
For more details about $http configs and how to set default configs, look at Angularjs Documentation
Your approach is a little confused, and therefore very hard to debug.
its good practice (IMO) to separate your api endpoints from the controller action that renders the page. Coupling them together is going to seriously limit the extensibility of your application.
Its possible that you're failing one part of the complex if statement in your controller action; this is making it hard to debug.
Its also good practice when writing an api to provide the client with an idea of what went wrong on a call. (even if its only you accessing the api)
Looking at your code, it also looks like your getting mixed up in processing the request. Your'e validating the submission based upon it being a Product, and asking symfony to process the data on that basis, but then inside your submitted if statement, pulling out the data again..
You can still harness the symfony form validation by decoupling it and submitting this way.
/**
* If your using annotated routing do this, or make the equivelent in your yaml file.
* #Route("/api/product/create", name="api_product_create")
*/
public function productAction(Request $request)
{
$data = json_decode($request->getContent(), true);
if(!$data)
{
// youll want to handle this exception with a listener or somesuch so that it sends back a nice neat message to your client
throw new InvalidArgumentException('Invalid json');
}
$product = new Product();
// create your form as you did before.
$form = $this->createForm(ProductType::class,$product);
// this tells symfony to fill out the form, as if it was submitted conventionally.
$form->submit($data);
// now we can check for valid (you dont need to check submitted, as valid will do that anyway)
if($form->isValid())
{
// persist the new object
$em = $this->getDoctrine()->getManager();
$em->persist($prod);
$em->flush();
// create a new set of return data
$return = [
'status' => 'success',
'productId' => $product->getId(),
];
return new JsonResponse($return, 201);
}
// oops, something went wrong, find out and report it
$return = [
'status' => 'error',
'uri' => $request->getPathInfo(),
'errors' => (string) $form->getErrors(true, false),
];
return new JsonResponse($return, 400);
}
then, in your template, render the url to the endpoint properly.
url: {{ path('api_product_create') }},
this is just an example, and may not totally fit your usecase, but as you can see, once decoupled its much easier to find out what went wrong and where.
Useful resources:
https://knpuniversity.com/screencast/symfony-rest2/validation-errors-test (whilst payed to see the video, the transcript is free)
http://symfony.com/doc/current/form/direct_submit.html
thank you all for ansewring my question.. the informations were so helpfull .. otherwise the solution was to seprate the two actions in symfony controller and adding a request header to the $http method and it works very well .. thank u all

how to use response.redirect in webapi+asp.net?

I want to redirect to another .aspx page from WebAPI. I have used this code but it is not working:
string url = "http://localhost:61884/UserList.aspx";
System.Uri uri = new System.Uri(url);
return Redirect(uri).ToString();
You don't. (or your description of the problem is not accurate)
Web API is meant to retrieve data or persist data, it is a way to interact with the server from the client without having to do the traditional form post or page request calls. The caller (javascript based on your question tag angularJs) needs to execute the redirect once the results from the call to the Web API are retrieved.
This is good SOC (separation of concerns), the business logic in the Web API should not care about routes (angularjs) / web pages.
Even if you wanted to the Web API, because of how its called, can't redirect the client.
Summary: The Web API code itself should not any type of redirecting of the client. The client should handle this.
Sample call to web api and redirect from angular code:
$http({
url: "/api/SomeWebApiUrl",
data: {},
method: "POST",
headers: { 'Content-Type': "application/json" },
responseType: "json"
}).then(function (response) {
if(response.data.somethingToCheck === someConditionThatWarrentsRedirect)
$window.location.href = "~/someOtherUrl/";
});
try something like this:
var response = Request.CreateResponse(HttpStatusCode.Moved);
string fullyQualifiedUrl = Request.RequestUri.GetLeftPart(UriPartial.Authority);
response.Headers.Location = new Uri(fullyQualifiedUrl);
Hope that helps.
Redirect from asp.net web api post action
public HttpResponseMessage Post()
{
// ... do the job
// now redirect
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("http://www.abcmvc.com");
return response;
}

web api 2 post with parameter - must use json.stringyfi

I'm using angularjs and I'm trying to make a HttpPost call to my web api.
My api method:
[HttpPost]
[Route("authentication/getkey")]
public IHttpActionResult GetKey([FromBody]string password) {
//Do stuff
}
my call:
service.getKey = function (password) {
return $http.post('api/authentication/getkey', JSON.stringify(password))
.then(function(result) {
return result.data;
});
}
Now this works fine, but do I really need to use JSON.stringify? I tried sending it like below, but all of them get password = null. Do I have to use JSON.stringify or am I doing it wrong in my other examples?
//Doesnt work
service.getKey = function (password) {
return $http.post('api/authentication/getkey', password)
.then(function(result) {
return result.data;
});
}
//Doesnt work
service.getKey = function (password) {
return $http.post('api/authentication/getkey', {password})
.then(function(result) {
return result.data;
});
}
If you don't want to use JSON.stringify, the other option will be to send the data as application/x-www-form-urlencoded as pointed in other answer as well. This way you are sending the data as form data. I'm not sure about the syntax of the $http.post Shortcut method but the idea is the same.
service.getKey = function (password) {
$http({
method: 'POST',
url: 'api/authentication/getkey',
data: $.param({ '': password }),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function(result) {
return result.data;
});
From Microsoft's Web API official documentation about Parameter Binding in ASP.NET Web API:
When a parameter has [FromBody], Web API uses the Content-Type header to select a formatter. In this example, the content type is "application/json" and the request body is a raw JSON string (not a JSON object).
Angular $http service sends Content-Type: application/json as header by default in POST requests, as you can see from the official docs, so Web API is trying to bind your request body using his JsonFormatter. Because of this you have to provide him a well formatted Json string (not a Json Object with a string inside) to correctly bind his raw string parameter.
As a side note, you could also send a request using application/x-www-form-urlencoded as Content-Type header, but then you will have to format your body as form parameters (using something similar to jQuery $.param( .. ))

How to send data from angular js to laravel 5 server

I am trying to send data from angular js to server.. Laravel5 is running on my server.. I can fetch data using this but can not send data.. My code is bellow
AngularJs Code:
var request = $http({
method: "get",
url: "http://www.myserver.com/json",
data: { email: $scope.email },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
request.success(function (data) {
alert(data.email);
});
Server code :
route is Route::get('json','JsonController#Json_login');
Controller code is
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Input;
class JsonController extends Controller
{
public function Json_login()
{
$email = Input::get('email');
$arr_Id_Status=array('email'=>$email);
echo json_encode($arr_Id_Status);
}
}
But it giving me null alert
Sounds like you should be using a POST rather than a GET request. You would need to create an appropriate POST route on your server but it's pretty much the same syntax on the client side, just change GET to POST.
var request = $http({
method: "POST",
url: "http://www.saadetera.com/json",
data: { email: $scope.email },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function (data) {
alert(data.email);
});
Not used Laravel for a while but it would be something like:
Route::post('json','JsonController#handleLoginRequest');
Ideally, sending data will require a POST method while fetching will be using a GET method. Let's make the complete flow assuming you want to call a controller called your_controller and use its your_method function :
This suits for Laravel 5
Laravel Controller :
use Illuminate\Http\Request;
public function your_method(Request $request)
{
$data = $request->input(my_data);
//Server side data processing here
//Returning Json or anything else here
return response()->json(your_answer_here);
}
Route :
Route::post('your_url', ['uses' => 'your_controller#your_method']);
AngularJS : Here is the chunk of code allowing data sending, it requires $http service. Let's assume your data is contained in the my_data object.
$http.post('your_url', my_data)
.then(you_callback_success, your_callback_fail);

Slim, Postman and AngularJs : $app->request->getBody() vs $app->request->post()

I'm a beginner. I've written a test application made of an AngularJs GUI on the client side and a PHP API on the server side.
This is the angular service handling the requests
myApp.factory('Book', ['$resource', 'API_URL', function($resource, API_URL){
return $resource(API_URL + '/books/:bookId', {bookId: '#bookId'}, {
get: { method: 'GET', isArray:true },
update: { method: 'PUT'},
save: { method: 'POST'},
delete: {method:'DELETE'},
});
}]);
When I submit a book from the Angular app I can catch the POST in Slim by using
$post_a = json_decode($app->request->getBody());
//$post_b = $app->request->post(); //this would be empty
When I use Postman and I perform a POST I can catch the POST in Slim by using
//$post_a = json_decode($app->request->getBody()); // this would be empty
$post_b = $app->request->post();
I don't get why there is this difference. Could you please explain?
Am I not meant to catch the post just with $app->request->post(); in both the cases? Why the post coming from Angular can be caught only with $app->request->getBody()?
The $app->request->post() method retrieves key/value data submitted in a application/x-www-form-urlencoded request. If the request uses a different content-type (e.g. application/json), you can retrieve the raw request body with the $app->request->getBody() method and decode it as necessary. Let me know if you have further questions.
You could still use
$post_b = $app->request->post()
in Slim.
As long as you call this REST service from html form (AngularJS) by passing the data as form value formatted instead of as JSON.
If in AngularJS you have the data in JSON format, you have to translate it first into form. Below is the example how to invoke this REST service:
Object.toparams = function ObjecttoParams(obj) {
var p = [];
for (var key in obj) {
p.push(key + '=' + encodeURIComponent(obj[key]));
}
return p.join('&');
};
$http({
method: 'POST',
url: url,
data: Object.toparams(myobject),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
myobject is the data in JSON format that is going to be created
Thanks Josh..Your answers works for me.
Steps to follow:
1.You need to send request in json format under raw tab like this:
{"username":"admin","password":"admin"}
2.You need to set Content-Type to application/json in the headers.
That's it and it will work.

Resources