POST <target url> 419 (unknown status) - can't post data in Laravel - javascript

I'm trying to make a DOM event where the user clicking a table row's header (th) cell will delete the corresponding row from the database that supplies the table's data.
This code worked as intended framework-less, by just POST'ing an AJAX containing the row's id info from index.php to delete.php which then ran a sql query.
However, after moving the site to Laravel I ran into an error:
POST http://sandbox.app/delete 419 (unknown status)
The JavaScript piece responsible for attaching the delete event and posting the id through AJAX:
function attachDelete() {
$("#mainTable tbody tr th").on("click", function(e){
console.log(e.target.innerText + " was clicked");
var token = $('meta[name="csrf-token"]').attr('content');
var id_to_delete = e.target.innerText;
$.ajax({
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
type: 'POST',
dataType: 'text',
url: 'delete',
data: {
'id_to_delete': id_to_delete,
"_method": 'POST',
"_token": token
},
success: function () {alert("Deleted!"); },
failure: function() {alert("Error!");}
});
});
}
attachDelete();
The console.log(e.target.innerText + " was clicked"); goes off.
However, the success / error messages do not appear.
Going to http://sandbox.app/delete directly brings up a Laravel error window with lots of text, and this part highlighted:
protected function methodNotAllowed(array $others)
{
throw new MethodNotAllowedHttpException($others);
}
I've added the token variables after reading answers to related questions on StackOverflow. This didn't help.
In case it matters, the route:
Route::post('/delete', 'TasksController#delete');
The controller :
class TaskController extends Controller
{
public function delete()
{
include 'config.php';
$stmt = $pdo->prepare('DELETE FROM food WHERE id = :id');
$stmt->execute(['id' => $_POST['id_to_delete']]);
}
}
The code inside delete() used to just be the contents of a delete.php file in the old, framework-less site, where everything worked.
I've tried doing it without the controller by creating a delete.php view (with the same code as the delete() function). It didn't make a difference though:
Route::post('/delete', function () {
return view('delete');
});

Well, it seems if you are communicating with POST at the backend. So, you should be configuring your routes on the api.php instead of web.php
Place your route associated with controller
Route::post('/delete', 'TasksController#delete');
Inside api.php file.

Related

Asp .Net Core 2.2 Razor Pages Ajax Call Post not working

I've done so many ajax in razor pages but i can't figure out why this does not work. It keeps giving me error 400 on dev tools. It does not reach the page handler no matter what.
<script>
$.ajax({
url: "/Account/Users/Index?handler=Delete",
type: "POST",
data: {
id: id
},
success: function () {
swal("Utilizador Desactivado!", {
icon: "success",
});
},
error: function (xhr, ajaxOptions, thrownError) {
swal("Falha na ligação ao servidor. Tente novamente mais tarde.");
}
});
</script>
page handler
public async Task<IActionResult> OnPostDeleteAsync(int? id)
{
if (id == null)
{
return NotFound();
}
var user = await _context.Users.FindAsync(id);
if (user != null)
{
user.IsActivo = false;
_context.Users.Attach(user).Property( u => u.IsActivo).IsModified = true;
await _context.SaveChangesAsync();
}
return RedirectToPage("./Index");
}
I tried many url combinations and none work. I don't see what is wrong in here....
EDIT
It seems like the problem is the anti forgery token not being validated on razor page.
I wrote Ignore Anti forgery Token on the page model and everything works correctly
As you've already found out it's the anti forgery token, that is ruining your day.
Now, if you are inside a form, asp.net core will create a hidden input with that token for you. If you are not working with a form on your page, you'll have to call #Html.AntiForgeryToken(), which will add the token for you.
Still, this will not resolve the Bad Request for you. You have to add it to your ajax call:
$.ajax({
url: "/Account/Users/Index?handler=Delete",
type: "POST",
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN", $('input:hidden[name="__RequestVerificationToken"]').val());
},
data: {
id: id
},
});
Additionally, add this line to your Startup.cs file:
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
I don't know what you mapping of URL use, but as usual it consists of controllerName/actionName/. In your case try to use:
url: "/Account/OnPostDeleteAsync"
or
url: "/Users/OnPostDeleteAsync"
but if your URL is correct, then try to use [FromForm] attribute
public async Task<IActionResult> OnPostDeleteAsync([FromForm]int? id)
I hope this will help

Vue js Ready function is not triggered

I have this vue function where there are basically two methods. The first one postStatus is used to save a post just after the user clicks on the save button, and the other one getPosts is used to retrieve all previous posts of that user from the database.
Here is the vue.js, where there is an ajax call to a controller (in Laravel 5.3)
$(document).ready(function () {
var csrf_token = $('meta[name="csrf-token"]').attr('content');
/*Event handling within vue*/
//when we actually submit the form, we want to catch the action
new Vue({
el : '#timeline',
data : {
post : '',
posts : [],
token : csrf_token,
limit : 20,
},
methods : {
postStatus : function (e) {
e.preventDefault();
//console.log('Posted: '+this.post+ '. Token: '+this.token);
var request = $.ajax({
url : '/posts',
method : "POST",
dataType : 'json',
data : {
'body' : this.post,
'_token': this.token,
}
}).done(function (data) {
//console.log('Data saved successfully. Response: '+data);
this.post = '';
this.posts.unshift(data); //Push it to the top of the array and pass the data that we get back
}.bind(this));/*http://stackoverflow.com/a/26479602/1883256 and http://stackoverflow.com/a/39945594/1883256 */
/*request.done(function( msg ) {
console.log('The tweet has been saved: '+msg+'. Outside ...');
//$( "#log" ).html( msg );
});*/
request.fail(function( jqXHR, textStatus ) {
console.log( "Request failed: " + textStatus );
});
},
getPosts : function () {
//Ajax request to retrieve all posts
$.ajax({
url : '/posts',
method : "GET",
dataType : 'json',
data : {
limit : this.limit,
}
}).done(function (data) {
this.posts = data.posts;
}.bind(this));
}
},
//the following will be run when everything is booted up
ready : function () {
console.log('Attempting to get the previous posts ...');
this.getPosts();
}
});
});
So far the, first method postStatus is working fine.
The second one is supposed to be called or fired right at the ready function, however, nothing happens. I don't even get the console.log message Attempting to get the previous posts .... It seems it's never fired.
What is the issue? How do I fix it?
Notes: I am using jQuery 3.1.1, Vue.js 2.0.1
I see that you are using Vue 2.0.1. There is no ready method in Vue 2.0 and above.
Here is the link to list of all Vue 2.0 changes: https://github.com/vuejs/vue/issues/2873
As mentioned in the page above, you can use mounted instead of ready.
Not an issue, but just a note: You are mixing jQuery and Vue extensively. If you need jQuery only for http related functions, you may instead use vue-resource - https://github.com/vuejs/vue-resource
EDIT: Update on vue-resource
As pointed out by #EmileBergeron in the comments, vue-resource was retired way back in November 2016 itself (few weeks after I provided this answer with that last paragraph on vue-resource). Here is more info on the same:
https://medium.com/the-vue-point/retiring-vue-resource-871a82880af4
#Mani's suggestion of using mounted(){} works on the component that's not hidden. If you like to run a function in the component when visible and the elements which are hidden using conditions like v-if="" or v-show="" then use updated(){}.

Laravel Using AJAX to pass Javascript variable to PHP and retrieve those

How can I use Ajax to pass a Javascript variable to Php and retrieving those?
I am using a Jquery Ui Slider and on each slide I want to pass the javascript slider value to php so to say.
I have no ( not much ) experience in Ajax and really appreciate help.
This is how my slider looks:
$("#sliderNumCh").slider({
range: "min",
min: 0,
max: 20,
step: 1,
value: numbersOfChapters,
change : function(e, slider){
$('#sliderAppendNumCh').empty();
var i = 0;
var sliderValue = slider.value;
var getSliderVal = document.getElementById('sliderValue').value = sliderValue;
$.ajax({
type: 'POST',
url: '',
headers: {'X-Requested-With': 'XMLHttpRequest'},
data: {
value: getSliderVal
},
success: function (option) {
console.log(getSliderVal);
}
});
...
}
})
My route example:
Edit my route looks like this now:
Route::post('edit/{productID}', ['as' => 'editProductPost', 'uses' => 'ProductController#editProduct']);
Edits what I have tried:
url: '{{ route("editProductWeb") }}',
and got this error:
POST http://localhost/myApp/public/product/edit/%7BproductID%7D 500 (Internal Server Error)
and tried this:
url: 'edit',
and got this error:
POST http://localhost/myApp/public/product/edit 500 (Internal Server Error)
Edit my edit controller method:
public function editProduct($productRomID = 0)
{
$product = ProductRom::find($productID);
$sheets = Chapters::where('product_id', '=', $productID)->get();
$productId = $product->id;
$sheetCount = count($sheets);
return view('product.edit', [
'productId' => $productId,
'product' => $product,
'sheets' => $sheets,
'sheetCount' => $sheetCount,
'type' => 'edit',
'route' => 'updateProductRom'
]);
}
Edit using haakym suggestion so far:
$.ajax({
type: 'post',
url: "{{ Route('editProduct', $product->id) }}",
headers: {'X-Requested-With': 'XMLHttpRequest'},
data: {
value: getSliderVal,
productId : getPrId
},
success: function (option) {
console.log(getSliderVal);
}
});
does print me the id + the current slider value in my debug, so that works so far. Now I need to get that value and use it in my view(php) any suggestion how to proceed?
using this in my controller method:
$sliderValue = $request->input('value');
returns me
null
Edit I also tried this:
$sliderValue = Input::get('value');
which also returned me
null
Edit I added a Log:
Log::info(Input::all());
This shows the correct slider value and product id on slide.
But my Input::get('value') still returns me null
Edit I think I should add this information:
I changed my routes to this now:
Route::get('edit/{productID}', ['as' => 'editProduct', 'uses' => 'ProductController#editProduct']);
Route::post('edit/{productID}', ['as' => 'editProductPost', 'uses' => 'ProductController#editProductPost']);
The get shows the data from the database for a specific product and shows them in my view, I added the post one to post the slidervalue data to the editProductPost method and returns afterwards the value(sliderValue) in the edit view, is this correct?(Btw still does not work)
EDIT
If I put this in my controller method:
if ($request->isMethod('post')){
return response()->json(['response' => 'This is post method']);
}
return response()->json(['response' => 'This is get method']);
I keep getting the following error (if I slide):
POST http://localhost/myApp/public/product/edit/54 500 (Internal
Server Error)
I have this in my head:
<meta name="csrf-token" content="{{ csrf_token() }}">
and put this before my ajax post:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
EDIT:
Doing this returns the correct current slider value in the logs:
Log::info($request->get('value'));
I tried this:
return view('productRom.edit', [
'value' => $value,
]);
But I get an error in the console:
Failed to load resource: the server responded with a status of 500
(Internal Server Error) http://localhost/myApp/public/product/edit/73
As #julqas stated you need to include the URL in your $.ajax() method.
As you have a named route editProduct, you can output the link using blade:
$.ajax({
type: 'POST',
url: '{{ route("editProduct" }}',
...
Edit 1:
Your route is get and your ajax method is post, I guess this is the issue. You need to make them the same.
If you change the route to post you will need to add the CSRF token to the ajax request when it is sent. There is some guidance on the docs how to do this here:
https://laravel.com/docs/5.2/routing#csrf-x-csrf-token
The docs recommend adding this in your HTML head:
<meta name="csrf-token" content="{{ csrf_token() }}">
then use the following code before sending the request:
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
alternatively you can add it to the request in the ajax call.
Edit 2
A side point - I was just guessing what the error is, it would have been better if I'd asked you if you could debug it yourself in order to see what the error was. Learning to debug ajax requests is very useful and not too difficult.
The best way to do that is by using the developer console in your browser of choice when making the ajax request. If you're using Chrome for example open Developer tools and then click on the Network tab before making your request. After making the request you can inspect the request and its details. Hope that helps!
Edit 3
I would change your editProduct() method to not accept any parameter and instead get the id value for the product from the request
public function editProduct()
{
// value here is referring to the key "value" in the ajax request
$product = ProductRom::find(\Request::get('value');
...
}
Consider changing the value key in your json to something more useful, such as productId
data: {
productId: getSliderVal
}
you haven't entered value for 'url'. Create any route then put it in url:'{any_route_name}' and then check in console weather your value has been posted or not
You have to do some R&D at your level for this .

ajax post return the html

I have this ajax function (refer below)
$.ajax({
url: "processor.php",
type:"POST",
data: { 'id' : "itemid, 'itemname' : itemname, 'itemdesc' : itemdesc" } ,
success:function(e){
if(($.trim(e) == "success")){
alert("success");
}else{
alert(e);
}
},error:function(){
alert("critical error");
}
});
assume that I already have the linked script of jquery and the content of those variables that has been declared on the data argument inside ajax function. Now I have a processor.php (refer below)
//this is the processor php
echo "success";
so base from above references, the ajax function submit a post request to processor.php and then the processor.php will respond "success" string as declared with the "echo success" but what happen is it doesn't get the success response instead the whole html tags on the current page is pop up (alert), why?? any ideas, clues, recommendation, suggestion would be greatly appreciated. Thank you.
PS: i know the response is not success but why it popup (alert) the whole html tags in the current page?
Try this i think your are passing parameter is wrong way.i just create an example change this code as per your requirement.
$.ajax({
url: "script.php",
type:"POST",
data: { id : itemid, itemname : itemname, itemdesc : itemdesc },
success: function(data, status, settings)
{
alert(The request URL and DATA);
}
,
error: function(ajaxrequest, ajaxOptions, thrownError)
{
alert("error");
}
});
there is syntax error in posted data and you probably have a redirect to new page instead of processor.php.
EDIT
Also make sure that processor.php returns only the word "success" and there is no more html tags in the source of page.
wrong syntax:
data: { 'id' : "itemid, 'itemname' : itemname, 'itemdesc' : itemdesc" }
suggested change:
data: { id : itemid, itemname : itemname, itemdesc : itemdesc }
I've been experienced that before, check your folder and file structure and if you're running server side script (such as php) or communicating with database, check your virtual host configuration.

Calling a C# method from JavaScript

I want to to call a method GetAccount from my controller AccountController.cs, in my JavaScript factory LoginFactory.js. Something like this:
AccountController.cs:
public Account GetAccount(string userName)
{ ... }
LoginFactory.js:
if(x>y) {
var account = <%AccountController.GetAccount(someParam);%>
}
I've tried using [WebMethod] and Ajax, but I can't get it to work: I get a 404 response.
Assuming your GetAccount method can be reached at /Account/GetAccount when your application runs, you could use the following:
$.ajax({
type: 'GET',
url: '/Account/GetAccount',
data: { 'username' : 'a-username' },
dataType: 'json',
success: function(jsonData) {
alert(jsonData);
},
error: function() {
alert('error');
}
});
Note - this is dependant on jQuery.
This causes the browser to make a request to /Account/GetAccount as if you had done so by entering the URL in the URL bar, but of course, captures the returned json for use in your client side (javascript) script.
If this returns a 404, it would be worth checking your routing.

Categories

Resources