1
votes

I am trying to access a URL via AJAX in Magento 2's admin area. I have tried many things but every time the response is 404 Forbidden.

Firefox's console shows this: Firefox Console: Headers Firefox Console: Params

This is the code my module has:

Vendor/Module/etc/module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_Module" setup_version="1.0.0">
    </module>
</config>

Vendor/Module/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="adminhtml">
            <module name="Vendor_Module" before="Magento_Backend" />
        </route>
    </router>
</config>

AJAX JS Code using Prototype:

new Ajax.Request('<?php /* @escapeNotVerified */ echo $block->getAdminUrl(); ?>adminhtml/action/add', {
    method: 'post',
    parameters: {'order_id' : <?php /* @escapeNotVerified */ echo $block->getOrderId(); ?>},
    onSuccess: function(response) {
        console.log($response);
        this.add();
    }.bind(this)
});

Vendor/Module/Controller/Adminhtml/Action/Add.php

<?php
namespace Vendor\Module\Controller\Adminhtml\Action;

class Add extends \Magento\Backend\App\Action
{
    protected $_context;
    protected $_pageFactory;
    protected $_jsonEncoder;

    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\Json\EncoderInterface $encoder,
        \Magento\Framework\View\Result\PageFactory $pageFactory
    ) {
        $this->_context = $context;
        $this->_pageFactory = $pageFactory;
        $this->_jsonEncoder = $encoder;
        parent::__construct($context);
    }

    public function execute()
    {
        $response = array('status' => 'success');
        $this->getResponse()->representJson($this->_jsonEncoder->encode($response));
        return;
    }
}

Please tell me how I can access this admin URL via AJAX.

2
404 Forbidden? That's weird. 404 normally means Not Found. The status code for Forbidden should be 403. Something is not configured properly, although I don't think it's the code you've shown here which is causing it. - ADyson
@Shahid any solution? - Mahmoud Ismail

2 Answers

0
votes
<?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="adminhtml" frontName="xyz">
            <module name="Vendor_Module" before="Magento_Backend" />
        </route>
    </router>
</config>

I am convinced that missing frontName in the route configuration file is the reason why error 404 is popping up so replace xyz with your frontName as specified above

0
votes

I had tried all of the above methods but non of them are working or incomplete so I had decided to answer it in details: Following will be module minimal diagram

enter image description here

1)

<?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 frontName="groupproduct" id="groupproduct">
            <module before="Magento_Backend" name="Textmimedia_Partpicker"/>
        </route>
    </router>
</config>

2)

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Levosoft_Partpicker" setup_version="1.0.0"/>
</config>

3) Need to declare admin router

    <?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 frontName="groupproduct" id="groupproduct">
            <module before="Magento_Backend" name="Levosoft_Partpicker"/>
        </route>
    </router>
</config>

4)

<?php


namespace Levosoft\Partpicker\Controller\Adminhtml\Imagetag;

/**
 * Class Save
 *
 * @package Levosoft\Partpicker\Controller\Adminhtml\Imagetag
 */
class Save extends \Magento\Backend\App\Action
{

    protected $resultPageFactory;
    protected $jsonHelper;

    /**
     * Constructor
     *
     * @param \Magento\Backend\App\Action\Context  $context
     * @param \Magento\Framework\Json\Helper\Data $jsonHelper
     */
    public function __construct(
        \Magento\Backend\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Framework\Json\Helper\Data $jsonHelper,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->resultPageFactory = $resultPageFactory;
        $this->jsonHelper = $jsonHelper;
        $this->logger = $logger;
        parent::__construct($context);
    }

    /**
     * Execute view action
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        try {
            return $this->jsonResponse('your response');
        } catch (\Magento\Framework\Exception\LocalizedException $e) {
            return $this->jsonResponse($e->getMessage());
        } catch (\Exception $e) {
            $this->logger->critical($e);
            return $this->jsonResponse($e->getMessage());
        }
    }

    /**
     * Create json response
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function jsonResponse($response = '')
    {
        return $this->getResponse()->representJson(
            $this->jsonHelper->jsonEncode($response)
        );
    }
}

Now Client Part which is actually bit tricky I am calling it in js file like somefilename.js

var ajaxRequest;
                var saveUrl = gpImageTagSaveUrl+'?isAjax=true'; //module url declared globally in module;

                ajaxRequest = $.ajax({
                    showLoader: true,
                    url: saveUrl,
                    data: {form_key: window.FORM_KEY},
                    type: 'POST',
                    dataType: 'json',
                    beforeSend: function () {
                        $('#loader').show();
                    }
                });
                //Show successfully for submit message
                ajaxRequest.done(function (response, textStatus, jqXHR) {
                    $("#ajaxResponse").html(response);
                    $('#loader').hide();
                });

                //On failure of request this function will be called
                ajaxRequest.fail(function () {
                    //show error
                    $("#ajaxResponse").html('Oops, An error occured, please' +
                        ' try again later!');
                    $('#loader').hide();
                });

gpImageTagSaveUrl is globel variable which will hold your modules url you can declare it in some js file like following

enter image description here

I had used catalog_product_edit.xml file because I want it at product edit location you can add it in your required file or in default.xml if required on all.

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="admin-1column"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="js">
            <block class="Magento\Backend\Block\Template" template="Textmimedia_Partpicker::js.phtml"
                   name="custom_js_backend"/>
        </referenceContainer>
    </body>
</page>

Now in js.phtml declare action url like following:

<script>
    require([
        "prototype"
    ], function () {
        window.gpImageTagSaveUrl = '<?= /** @noEscape */ $block->getUrl('groupproduct/imagetag/save')?>';
    });
</script>