Ajax Delete give 405 (Method Not Allowed) in laravel 6 - javascript

Don't understand why have to error in the method. What I do wrong?
I'm using Ziggy routing for js
management.site.destroy:
domain: null
methods: ["DELETE"]
uri: "management/site/{id}"
Have console error
DELETE http://localhost/blog/public/management/site 405 (Method Not Allowed)
have button and js on it
<button type="button" name="ok_button" id="ok_button" class="btn btn-danger">OK</button>
JS
$(document).on('click', '#ok_button', (function (e) {
var product_id = $(this).val();
var token = $("meta[name='csrf-token']").attr("content");
$.ajax({
url: route('management.site.destroy',product_id),
beforeSend:function(){
$('#ok_button').text('Deleting...');
},
type: 'delete',
data: {'product_id':product_id,
'_token': token,},
success: function (data) {
setTimeout(function(){
$('#confirmModal').modal('hide');
alert('Data Deleted');
location.reload();
}, 2000);
}
});
}));
Controller:
public function destroy($id)
{
$company_id = Auth::user()->company_id;
$item = Site::firstWhere(['company_id'=>$company_id,'id'=>$id]);
$item->delete();
return response()->json(['success' => 'Data is successfully Deleted']);
}
Route (Edited added full route) in patch and etc work fine
Route::group([ 'as'=>'management.','namespace' => 'Management', 'prefix' => 'management','middleware' => ['role:administrator'] ], function () {
Route::get('/', 'ManagementController#index');
Route::group(['as' => 'site.','prefix' => 'site'], function () {
Route::get('/','SiteController#index')->name('index');
Route::post('store','SiteController#store')->name('store');
Route::post('edit/{id}','SiteController#edit')->name('edit');
Route::get('edit/{id}','SiteController#edit')->name('edit');
Route::patch('','SiteController#update')->name('update');
Route::delete('{id}','SiteController#destroy')->name('destroy');
Route::get('{id}','SiteController#view')->name('view');
});

Is this:
Route::delete('{id}','SiteController#destroy')
wrapped in a Route group?
If it is not, then your delete() methods route will actually be /{id} and not management/site/{id}
In your console, run php artisan route:list to display the full list of registered routes for your application. Then check what the registered route is for your delete method.
Edit (Round 2)
So the registered route is:
| DELETE | management/site/{id} | management.site.destroy | App\Http\Controllers\Management\SiteController#destroy | web,role:administrator
This is expecting the delete request to be http://localhost/management/site/{id}
However, the error being returned indicates the path the request is making is incorrect:
DELETE http://localhost/blog/public/management/site 405 (Method Not Allowed)
It may well be that you have a relative path somewhere which is adding the /blog/public/ section of your URI!
TLDR;
http://localhost/blog/public/management/site != http://localhost/management/site/{id}

Related

cypress cy.route not behaving consistently

I am trying to stub out a route using cypress 5.2. I have a simple function to do that:
function mockAlertsResponses(){
cy.route({
method: "GET",
url: "/api/polling/alerts/statistics*",
response: {
total: 2,
...
}
});
}
In one set of tests, this works just fine:
describe("admin and read only permissions", () => {
it ("all action bar items are enabled with admin permissions", () => {
cy.login("user", "password");
mockAlertsResponses();
// Click alert to enable all buttons
cy.get("#1-checkbox").click()
cy.get("#mark-alert-button").should("be.enabled");
cy.get("#delete-alert-button").should("be.enabled");
});
// ... a few more similar tests
});
However, in another set of tests, I use the same function:
it("Logs in and out", () => {
cy.login("username", "password");
mockAlertsResponses()
cy.get("#vine-appbar").should("be.visible");
cy.get("#info-button").click();
cy.get("#info-menu-logout").click();
cy.get("#login-button");
cy.get("#vine-appbar").should("not.be.visible");
});
In this second set of tests, the routes are not stubbing properly, leading to errors and test failures. Here, you can see the route is not stubbed, but rather throws a 500 error:
I'm not sure what could be interfering here. I'm a bit new to cypress and I'm not even sure where to begin debugging this. Might the cy.server calls be interfering? Please let me know what more information we'd need to figure out why one set of stubs works and another doesn't.
If you're wondering, the login function has a call to cy.server and has its own cy.route as well:
Cypress.Commands.add("login", (username, password, admin = true) => {
const response = admin ? <jwt1> : <jwt2>
cy.server();
cy.route({
method: "POST",
url: "/api/login",
response
});
cy.visit("/logout");
cy.visit("/");
cy.wait(100);
cy.get("#login-error").should("not.be.visible");
cy.get("#login-username").type(username);
cy.get("#login-password").type(password);
cy.get("#login-button").click();
});

Laravel ajax post data

I have an eCommerce shop where I have to filter products by its categories.
I have to post an array of all filters in the controller, but I am getting this error
"message": "",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
"file": "C:\\xampp\\htdocs\\web_front\\vendor\\laravel\\framework\\src\\Illuminate\\Routing\\RouteCollection.php",
"line": 179
Here is my code:
<script>
$(document).ready(function () {
var categories = [];
$('input[name="cat[]"]').on('change', function (e) {
e.preventDefault();
categories = []; // reset
$('input[name="cat[]"]:checked').each(function()
{
categories.push($(this).val());
});
$.ajax({
type:"GET",
url:'advanced_filter/' + categories,
success:function(data){
console.log(data);
},
error: function(xhr,errmsg,err)
{
console.log(xhr.responseText);
}
});
});
});
</script>
web.php
Route::get('advanced_filter/{filters}', 'HomepageController#advanced_filter')->name('advanced_filter');
public function advanced_filter($filters)
{
dd($filters);
}
I am trying to show all the filters, so I can make a query to get all the products based on filters. I have created the script where I get all filters and want to post it in the controller. Please, can you see this? Thank you
first of all :
"exception":"Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
above exeption occur when route is not found . NotFoundHttpException has status 404
in your code you are passing array of categories in route params , which is syntactically wrong , so thats why failed to find route .
Route::get('advanced_filter', 'HomepageController#advanced_filter')->name('advanced_filter');
from frontend side : pass categories as query parameters
url will be :
/advanced_filter?queryParameter= ids of selected categories
/advanced_filter?categories=1,3,7
your ajax function will be :
$.ajax({
type:"GET",
url:`/advanced_filter?categories=${categories.join(',')}`,
success:function(data){
console.log(data);
},
error: function(xhr,errmsg,err){
console.log(xhr.responseText);
}
});
in your controller :
use Illuminate\Http\Request;
public function advanced_filter(Request $request)
{
$filter_categories=[];
if($request->has('categories')){
$filter_categories=$request->query('categories');
}
/* you can pass extra query parameter like sortBy,sortOrder,limit in url
`/advanced_filter?categories=1,3,7&limit=24&sortBy=name&sortOrder=desc`
*/
$sortBy=$request->has('sortBy')?$request->query('sortBy'):'id';
$sortOrder=$request->has('sortOrder')?$request->query('sortOrder'):'desc';
$limit = $request->has('limit')?$request->has('limit'):12;
/* assuming you have models with relations */
$query = Products::query();
$query->with('categories');
if(count($filter_categories)>0){
$query->whereHas('categories', function ($q) use ($filter_categories) {
$q->whereIn('categories.id',$filter_categories);
});
}
$query->orderBy($sortBy,$sortOrder);
$products = $query->paginate($limit);
return response()->json($products);
}

How do I retrieve an async value for a restangular parameter?

I need to retrieve a value from an async service to add as a parameter to every rest call. The casService.getProxyTicket() is an $http call...
I have the following code :-
myFactories.factory('myFactory', [
'Restangular'
, 'casService'
, function (Restangular
, casService) {
return Restangular.withConfig(function (config) {
config.setBaseUrl('https://host:port/somecontext/rest');
config.addFullRequestInterceptor(function (element
, operation
, route
, url
, headers
, params
, httpConfig) {
... What do I need to do here?
casService.getProxyTicket(url).then(function(st){
console.log('proxyTicket = ' + st.data.ticket);
});
params.ticket = ?????? <= st.data.ticket
...
return {
element: element
, headers: headers
, params: params
, httpConfig: httpConfig
}
});
}).service('myCollection');
}]
);
...thanks in advance!!!!
Ok, my lack of understanding coming from a backend developer's background...
This can/should NOT be done this way! I was trying to make the call to get a proxy ticket synchronous.... DON'T DO IT!
What I did was to rearrange my code thus ...
function readItem(id) {
var endpoint = myFactory.one(id);
return casService.getProxyTicket(endpoint.getRestangularUrl())
.then(function (response) {
return endpoint.get({ticket: response.data.proxyTicket});
}).then(function (response) {
return response.plain();
});
}
...works like a charm!

Symfony: Send variable throught GET to handler from Ajax

I would like to use AJAX in my Symfony3.0.3 project.
The communication works, but I can't get variable from JS to the handler. In the direction handler to JS, it works fine.
I'm trying to get the variable from the request with "$request->query->get('id'))" but I only get "null".
In an other way I'm trying to use the variable from the URL but I get this error:
"An exception has been thrown during the rendering of a template ("Some mandatory parameters are missing ("id") to generate a URL for route "admin_ajax".") in CommonBundle:Default:index.html.twig at line 421."
I don't mind using a solution or an other (I'll use the best one depending of your advices), but I still would like the solution for both error.
JS
function selectClient(idClient)//idClient = 1
{
alert(idClient);
$.post('{{path('admin_ajax')}}',{idClient: id},
function(response)
{
if(response.code == 100 && response.success)
{
alert(response.id);//Show null if using $request->query->get('id')) in handler but should be 1
}}, "json");
}
routing:
admin_ajax:
defaults: { _controller: CommonBundle:Default:getClient }
path: /ajax/{id}
handler:
public function getClientAction($id)
{
$request = $this->container->get('request_stack')->getCurrentRequest();
$isAjax = $request->isXMLHttpRequest();
if ($isAjax)
{
$response = array("code" => 100, "success" => true, "id" => $request->query->get('id'));
return new Response(json_encode($response));
}
$response = array("code" => 0, "success" => false);
return new Response(json_encode($response));
}
EDIT:
Thank for Rim, and Rvanlaak answer, I used the FOSJsRoutingBundle.
JS
function selectClient(idClient)
{
$.get(Routing.generate('ajax_getclient', { id:idClient }),
function(response)
{
if(response.code == 100 && response.success)
{
alert(response.id);
}
else
}, "json");
}
routing:
ajax_getclient:
defaults: { _controller: CommonBundle:Default:getClient }
path: /ajax/{id}
options:
expose: true
Note that the option "expose: true" was necessary to works.
Thats because the twig is executing before javascript so he is not reconizing the client id param
i had the same problem and resolve it using FOSJSRoutingBundle see this post :
Ajax url parametetr using Twig path

Backbone model.destroy() invoking error callback function even when it works fine?

I have a Backbone.js model that I'm trying to destroy when the user clicks a link in the model's view. The view is something like this (pseudocode because it's implemented in CoffeeScript which can be found at the bottom of the question).
var window.ListingSaveView = Backbone.View.extend({
events: {
'click a.delete': 'onDestroy'
},
onDestroy: function(event){
event.preventDefault();
this.model.destroy({
success: function(model, response){
console.log "Success";
},
error: function(model, response){
console.log "Error";
}
});
}
});
When I click the delete link in the browser, I always get Error logged to the console even though my server records successful destruction of the associated database record and returns a 200 response. When I refresh the page (causing the collection to re-render from the DB) the model I deleted will be gone.
One interesting this is that when I log the response in the error callback, it has statuscode 200 indicating success but it also reports statusText: "parseerror" whatever that means. There is no error in my server logs.
What am I doing wrong?
This is the response from the server:
Object
abort: function ( statusText ) {
always: function () {
complete: function () {
done: function () {
error: function () {
fail: function () {
getAllResponseHeaders: function () {
getResponseHeader: function ( key ) {
isRejected: function () {
isResolved: function () {
overrideMimeType: function ( type ) {
pipe: function ( fnDone, fnFail ) {
promise: function ( obj ) {
readyState: 4
responseText: " "
setRequestHeader: function ( name, value ) {
status: 200
statusCode: function ( map ) {
statusText: "parsererror"
success: function () {
then: function ( doneCallbacks, failCallbacks ) {
__proto__: Object
Here is the server action that destroy interacts with (Ruby on Rails)
# DELETE /team/listing_saves/1.json
def destroy
#save = current_user.team.listing_saves.find(params[:id])
#save.destroy
respond_to do |format|
format.json { head :ok }
end
end
And here is the actual CoffeeScript implementation of the Backbone View for people who prefer it like that:
class MoveOutOrg.Views.ListingSaveView extends Backbone.View
tagName: 'li'
className: 'listing_save'
template: JST['backbone/templates/listing_save']
events:
'click a.delete_saved': 'onDestroy'
initialize: ->
#model.bind 'change', this.render
render: =>
renderedContent = #template(#model.toJSON())
$(#el).html(renderedContent)
this
onDestroy: (event) ->
event.preventDefault() # stop the hash being added to the URL
console.log "Listing Destroyed"
#model.destroy
success: (model, response)->
console.log "Success"
console.log model
console.log response
error: (model, response) ->
console.log "Error"
console.log model # this is the ListingSave model
console.log response
#David Tuite comment:
"Ok I figured it out. It seems that Backbone expects the JSON response to be a JSON serialization of the record that was destroyed. However, Rails controller generators only return head :ok by default. I changed my JSON response to be render json: #listing_save where #listing_save is the record I just destroyed and it registers a success."
FYI - when you're doing a destroy, you don't need to return the full json for the destroyed model. you can return an empty json hash and it will work just fine. the only time you need to return the json for the model is on a save / update.
I had this same problem. In my delete method on the server (java), I didn't return anything. Just status 200/OK (or 204/No content). And so the "parsererror" problem was caused by jquery trying to convert the empty response into JSON, which failed (since "json" is the default data type).
My solution was to use the "text" dataType instead, which can be set in the options:
model.destroy({ dataType: "text", success: function(model, response) {
console.log("success");
}});
Your response must have status code 204 as you won't return any content. Since backbone uses a REST interface you should return different http status codes depending on the task.
Are you sure of your URL ? Do you append a .json at the end of the Backbone.Model url ? Since you check this on your server side (respond_to do |format| ... end), you might not send the correct head :ok response
Try with this destroy rails method to test if this is the problem :
def destroy
#save = current_user.team.listing_saves.find(params[:id])
#save.destroy
head :ok
end
Using the Slim Framework on an LAMP server you can add a Response Status to DELETE routes (or custom routes that don't return anything)
$app->response()->status(204);//204 No Content
this also sets the Content-Type back to text/html to allow for the empty body

Categories