1

I checked this and built a Controller that executes an ajax request sent on adminhtml through a button, but I get an error 404 on my console.

POST http://myurl/system_config/customAjax/key/ade007809d7e313c38d42de6c2fa64ad8/?isAjax=true 404 (Forbidden)

I don't think you should pay much attention to the word "Forbidden" as this is an open issue on their repo and I guess it will be corrected. The important thing here is the error 404, and why doesn't it call my controller. Any ideas?

etc\adminhtml\system.xml:

<field id="vendor_actionbutton" type="button" sortOrder="26" showInDefault="1" showInWebsite="1" showInStore="0">
    <frontend_model>Vendor\Module\Block\Adminhtml\System\Config\Mybutton</frontend_model>
</field>

Block\Adminhtml\System\Config\Mybutton.php:

<?php
namespace Vendor\Module\Block\Adminhtml\System\Config;

use Magento\Backend\Block\Template\Context;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;

class Mybutton extends Field
{
    /**
     * @var string
     */
    protected $_template = 'Vendor_Module::system/config/customajax.phtml';

    /**
     * @param Context $context
     * @param array $data
     */
    public function __construct(
        Context $context,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    /**
     * Remove scope label
     *
     * @param  AbstractElement $element
     * @return string
     */
    public function render(AbstractElement $element)
    {
        $element->unsScope()->unsCanUseWebsiteValue()->unsCanUseDefaultValue();
        return parent::render($element);
    }

    /**
     * Return element html
     *
     * @param  AbstractElement $element
     * @return string
     */
    protected function _getElementHtml(AbstractElement $element)
    {
        return $this->_toHtml();
    }

    /**
     * Return ajax url for send button
     *
     * @return string
     */
    public function getAjaxUrl()
    {
        return $this->getUrl('vendor_module/system_config/customAjax');
    }

    /**
     * Generate send button html
     *
     * @return string
     */
    public function getButtonHtml()
    {
        $button = $this->getLayout()->createBlock(
            'Magento\Backend\Block\Widget\Button'
        )->setData(
            [
                'id' => 'send_button',
                'label' => __('Send'),
            ]
        );

        return $button->toHtml();
    }
}

Controller\Adminhtml\System\Adminhtml\System\Config\CustomAjax.php:

<?php
namespace Vendor\Module\Controller\Adminhtml\System\Config;

class CustomAjax extends \Magento\Backend\App\Action
{
    /**
     * @var \Magento\Framework\Controller\Result\JsonFactory
     */
    protected $resultJsonFactory;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory

    )
    {
        parent::__construct($context);
        $this->resultJsonFactory= $resultJsonFactory;
    }

    public function execute()
    {
        $params = $this->getRequest()->getParams();
        $resultJson = $this->resultJsonFactory->create();

        return $resultJson->setData([
            'messages' => 'Successfully. Params: ' . json_encode($params),
            'error' => false
        ]);
    }
}

view\adminhtml\templates\system\config\customajax.phtml:

<script>
    require([
        'jquery',
        'prototype'
    ], function(jQuery){

        var sendSpan = jQuery('#send_span');

        jQuery('#send_button').click(function () {
            var params = {};
            new Ajax.Request('<?php echo $block->getAjaxUrl() ?>', {
                parameters:     params,
                loaderArea:     false,
                asynchronous:   true
        });

    });
</script>

<?php echo $block->getButtonHtml() ?>
<span class="send-indicator" id="send_span">
    <img class="processing" hidden="hidden" alt="Sending" style="margin:0 5px" src="<?php echo $block->getViewFileUrl('images/process_spinner.gif') ?>"/>
    <img class="sent" hidden="hidden" alt="Sended" style="margin:-3px 5px" src="<?php echo $block->getViewFileUrl('images/rule_component_apply.gif') ?>"/>
    <span id="send_message_span"></span>
</span>

etc\adminhtml\routes.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="module" frontName="module">
            <module name="Vendor_Module" before="Magento_Backend" />
        </route>
    </router>
</config>

Is it maybe this vendor_module/system_config/customAjax wrong? Should I write it differently? (I have seen another module working with this expression though)

4
  • if you are on the page of your module you can use */*/customAjax
    – Mr. Lewis
    Commented Sep 5, 2017 at 18:08
  • if you need any advice could you please provide your app/code/Vendor/Module/etc/frontend/routes.xml ?
    – Mr. Lewis
    Commented Sep 5, 2017 at 18:10
  • @Mr.Lewis Do you mean that I should replace url vendor_module/system_config/customAjax with */*/customAjax? Commented Sep 6, 2017 at 8:17
  • that is exactly what I mean
    – Mr. Lewis
    Commented Sep 6, 2017 at 11:42

4 Answers 4

0

I think you are missing your routes.xml file in app/code/Vendor/Module/etc/adminhtml/routes.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="admin">
        <route id="vendor_module" frontName="vendor_module">
            <module name="Vendor_Module" />
        </route>
    </router>
</config>
5
  • Now that I changed my routes.xml according to yours, I get an error 500, which I suppose is a good thing as it means that I have an error, but at least I manage to call the url, right? Commented Sep 6, 2017 at 8:16
  • @IriniKoutaki yes check your controller code now you have error in your code Commented Sep 6, 2017 at 8:17
  • @IriniKoutaki Enable error display by uncomment #ini_set('display_errors', 1); in app/bootstrap.php then re-run ajax call and open your console and there the Network tab so you can see the actual 500 error. I recommend to enable preserve log in the Network tab in case the page will be redirected because of the 500 error.
    – Mr. Lewis
    Commented Sep 6, 2017 at 11:52
  • 1
    I just corrected the error that was causing the 500 error: I had $this->resultFactory= $resultJsonFactory; instead of $this->resultJsonFactory= $resultJsonFactory; Commented Sep 13, 2017 at 14:47
  • and bottom of page you are using $this->resultJsonFactory Commented Sep 13, 2017 at 14:49
1

I experienced the same issue - receiving a 404 error on a custom ajax controller.

My ajax controller URL is retrieved using

$urlBuilder->getUrl('<frontname>/<action>');

and my controller file was at location

<module files>/Controller/Adminhtml/<Action.php>

After hours of debugging I found that the full path that Magento 2 creates for admin ajax requests is

<vendor>\<module>\controller\adminhtml\<action>\index

I then moved my controller file to be under:

<module files>/Controller/Adminthtml/<Action>/Index.php

The error was resolved - hope this helps someone else!

1

For those are looking for an example where you don't have deprecated classes for magento 2.4: controller:

use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\Result\JsonFactory;

class Usp implements HttpPostActionInterface
{
    /**
     * @var JsonFactory
     */
    protected $resultJsonFactory;

    /**
     * @param JsonFactory $resultJsonFactory
     */
    public function __construct(
        JsonFactory $resultJsonFactory
    ) {
        $this->resultJsonFactory = $resultJsonFactory;
    }

    public function execute()
    {
        $data = ['test'];
        $resultJson = $this->resultJsonFactory->create();
        $resultJson->setData($data);
        return $resultJson;
    }

}

In your phtml file:

<script>
    require(['jquery'], function($){
        $(document).ready( function() {
            $.ajax({
                url: "<?php echo $block->getUrl('tralala/index/usp'); ?>",
                type: "POST",
                data: { test:123 },
                showLoader: true,
                cache: false,
                success: function(response){
                }
            });
            return false;
        });
    });
</script>

your routes.xml file:

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
    <router id="standard">
        <route id="tralala" frontName="tralala">
            <module name="Vendor_Module"/>
        </route>
    </router>
</config>

Good luck !

0

I don't know how it is possible, but i had the same error and i fixed it adding to controller

/**
 * Array of actions which can be processed without secret key validation
 *
 * @var string[]
 */
protected $_publicActions = ['test'];

and it starts to work, but now it continues to work even if $_publicActions is removed or commented out.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.