What's best practice for an ajax request which involves - receiving some params in a request, loading data based on these params, processing this data, generating html and sending the html back in a json response?

For instance, say I have a product id that I pass as a param, I have to return html for related product listing html as a json response.

In M1 I would create a controller action and do the following:

$product = Mage::getModel('catalog/product')
$html = $this->getLayout()->getBlock('mycustom_module/block')- >setProduct($product)->toHtml();
$response('html' => $html);
$this->getResponse()->setHeader('Content Type: json');
return $this;

In my custom module's block class I would basically load the collection of related products for the product and form the html in the template and return the html output in the json. How do I go about doing this sort of a thing with M2?

Doing a similar thing as M1 while making sure I use best practices like using DI instead of object manager is good enough? Or would you design this sort of functionality differently?


2 Answers 2


Basiclly in your controller will have code below. I have not test yet but i will work. Class will extends Magento\Backend\App\Action

public function __construct(
    \Magento\Backend\App\Action\Context $context,
    \Magento\Framework\Json\Encoder $jsonEncoder,
    \Magento\Framework\Json\Decoder $jsonDecoder,
    \Magento\Framework\Controller\Result\RawFactory $rawResultFactory,
    \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
    \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility,
    \YourNamespace\Module\Model\EntityFactory $entityFactory
    $this->jsonDecoder = $jsonDecoder;
    $this->jsonEncoder = $jsonEncoder;
    $this->rawResultFactory = $rawResultFactory;
    $this->productRepository = $productRepository;
    $this->_catalogProductVisibility = $catalogProductVisibility;

Main function execute

 * @return \Magento\Backend\Model\View\Result\Redirect
public function execute()
    //Get json data from ajax POST
    $requestData = $this->getRequest()->getParam('param');
    $productId = $this->getRequest()->getParam('product_id');
    $result = ['success' => false];

    if ($requestData) {
        try {

            //decode data
            $menuData = $this->jsonDecoder->decode($requestData)
            //Do something : load model, collection here
            $products = $this->productRepository->getById($productId, false, $this->_session->getStore()->getId());  


            $result['success'] =  true;         

        } catch (\Exception $e) {
            $result['message'] = $e->getMessage();
    //Force header encode data to json
    $response = $this->rawResultFactory->create()->setHeader('Content-type', 'application/json');
    return $response->setContents($this->jsonEncoder->encode($result));

-- \Magento\Framework\View\LayoutFactory to create the block.
-- \Magento\Framework\Controller\Result\RawFactory to return Json format.
-- \Magento\Catalog\Api\ProductRepositoryInterface to get product

  * @var \Magento\Framework\View\LayoutFactory
protected $layoutFactory;

  * @var \Magento\Framework\Controller\Result\RawFactory
protected $resultRawFactory;

  * @var \Magento\Catalog\Api\ProductRepositoryInterface
protected $product

public function __construct(
    \Magento\Catalog\Api\ProductRepositoryInterface $product,
    \Magento\Framework\Controller\Result\RawFactory $resultRawFactory,
    \Magento\Framework\View\LayoutFactory $layoutFactory
) {

      $this->resultRawFactory = $resultRawFactory; 
      $this->layoutFactory = $layoutFactory;
      $this->product = $product;


public function execute() {

$productId = $this->getRequest()->getParam('product_id');

$product = $this->product->getById($productId);

$layout = $this->layoutFactory->create();

$block = $layout->getLayout()
                ->setData('product', $product)

/** @var \Magento\Framework\Controller\Result\Raw $resultRaw */

$resultRaw = $this->resultRawFactory->create();

//$this->getResponse()->setBody($block); <= We also can use setBody.

return $resultRaw;


Your Answer

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

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