diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Link/ActionViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Link/ActionViewHelper.php
index 090cecd44bb6375b6c7a3daf4872584f86d74a9f..808bfabf4fdcd3588ccea53d5a28fb1145f77fc7 100644
--- a/typo3/sysext/fluid/Classes/ViewHelpers/Link/ActionViewHelper.php
+++ b/typo3/sysext/fluid/Classes/ViewHelpers/Link/ActionViewHelper.php
@@ -17,11 +17,17 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Fluid\ViewHelpers\Link;
 
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Http\ApplicationType;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\HttpUtility;
 use TYPO3\CMS\Core\Utility\MathUtility;
-use TYPO3\CMS\Extbase\Mvc\RequestInterface;
-use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
+use TYPO3\CMS\Extbase\Mvc\RequestInterface as ExtbaseRequestInterface;
+use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder as ExtbaseUriBuilder;
 use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\Typolink\LinkFactory;
+use TYPO3\CMS\Frontend\Typolink\UnableToLinkException;
 use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractTagBasedViewHelper;
 
 /**
@@ -78,13 +84,122 @@ final class ActionViewHelper extends AbstractTagBasedViewHelper
         /** @var RenderingContext $renderingContext */
         $renderingContext = $this->renderingContext;
         $request = $renderingContext->getRequest();
-        if (!$request instanceof RequestInterface) {
+        if ($request instanceof ExtbaseRequestInterface) {
+            return $this->renderWithExtbaseContext($request);
+        }
+        if ($request instanceof ServerRequestInterface && ApplicationType::fromRequest($request)->isFrontend()) {
+            return $this->renderFrontendLinkWithCoreContext($request);
+        }
+        throw new \RuntimeException(
+            'The rendering context of ViewHelper f:link.action is missing a valid request object.',
+            1690365240
+        );
+    }
+
+    protected function renderFrontendLinkWithCoreContext(ServerRequestInterface $request): string
+    {
+        // No support for following arguments:
+        //  * format
+        $pageUid = (int)($this->arguments['pageUid'] ?? 0);
+        $pageType = (int)($this->arguments['pageType'] ?? 0);
+        $noCache = (bool)($this->arguments['noCache'] ?? false);
+        /** @var string|null $language */
+        $language = $this->arguments['language'] ?? null;
+        /** @var string|null $section */
+        $section = $this->arguments['section'] ?? null;
+        $linkAccessRestrictedPages = (bool)($this->arguments['linkAccessRestrictedPages'] ?? false);
+        /** @var array|null $additionalParams */
+        $additionalParams = $this->arguments['additionalParams'] ?? null;
+        $absolute = (bool)($this->arguments['absolute'] ?? false);
+        /** @var bool|string $addQueryString */
+        $addQueryString = $this->arguments['addQueryString'] ?? false;
+        /** @var array|null $argumentsToBeExcludedFromQueryString */
+        $argumentsToBeExcludedFromQueryString = $this->arguments['argumentsToBeExcludedFromQueryString'] ?? null;
+        /** @var string|null $action */
+        $action = $this->arguments['action'] ?? null;
+        /** @var string|null $controller */
+        $controller = $this->arguments['controller'] ?? null;
+        /** @var string|null $extensionName */
+        $extensionName = $this->arguments['extensionName'] ?? null;
+        /** @var string|null $pluginName */
+        $pluginName = $this->arguments['pluginName'] ?? null;
+        /** @var array|null $arguments */
+        $arguments = $this->arguments['arguments'] ?? [];
+
+        $allExtbaseArgumentsAreSet = (
+            is_string($extensionName) && $extensionName !== ''
+            && is_string($pluginName) && $pluginName !== ''
+            && is_string($controller) && $controller !== ''
+            && is_string($action) && $action !== ''
+        );
+        if (!$allExtbaseArgumentsAreSet) {
             throw new \RuntimeException(
-                'ViewHelper f:link.action can be used only in extbase context and needs a request implementing extbase RequestInterface.',
-                1639818540
+                'ViewHelper f:link.action needs either all extbase arguments set'
+                . ' ("extensionName", "pluginName", "controller", "action")'
+                . ' or needs a request implementing extbase RequestInterface.',
+                1690370264
             );
         }
 
+        // Provide extbase default and custom arguments as prefixed additional params
+        $extbaseArgumentNamespace = 'tx_'
+            . str_replace('_', '', strtolower($extensionName))
+            . '_'
+            . str_replace('_', '', strtolower($pluginName));
+        $additionalParams ??= [];
+        $additionalParams[$extbaseArgumentNamespace] = array_replace(
+            [
+                'controller' => $controller,
+                'action' => $action,
+            ],
+            $arguments
+        );
+
+        $typolinkConfiguration = [
+            'parameter' => $pageUid,
+        ];
+        if ($pageType) {
+            $typolinkConfiguration['parameter'] .= ',' . $pageType;
+        }
+        if ($language !== null) {
+            $typolinkConfiguration['language'] = $language;
+        }
+        if ($noCache) {
+            $typolinkConfiguration['no_cache'] = 1;
+        }
+        if ($section) {
+            $typolinkConfiguration['section'] = $section;
+        }
+        if ($linkAccessRestrictedPages) {
+            $typolinkConfiguration['linkAccessRestrictedPages'] = 1;
+        }
+        $typolinkConfiguration['additionalParams'] = HttpUtility::buildQueryString($additionalParams, '&');
+        if ($absolute) {
+            $typolinkConfiguration['forceAbsoluteUrl'] = true;
+        }
+        if ($addQueryString && $addQueryString !== 'false') {
+            $typolinkConfiguration['addQueryString'] = $addQueryString;
+            if ($argumentsToBeExcludedFromQueryString !== []) {
+                $typolinkConfiguration['addQueryString.']['exclude'] = implode(',', $argumentsToBeExcludedFromQueryString);
+            }
+        }
+
+        try {
+            $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
+            $cObj->setRequest($request);
+            $linkFactory = GeneralUtility::makeInstance(LinkFactory::class);
+            $linkResult = $linkFactory->create((string)$this->renderChildren(), $typolinkConfiguration, $cObj);
+            $this->tag->addAttributes($linkResult->getAttributes());
+            $this->tag->setContent($this->renderChildren());
+            $this->tag->forceClosingTag(true);
+            return $this->tag->render();
+        } catch (UnableToLinkException) {
+            return (string)$this->renderChildren();
+        }
+    }
+
+    protected function renderWithExtbaseContext(ExtbaseRequestInterface $request): string
+    {
         $action = $this->arguments['action'];
         $controller = $this->arguments['controller'];
         $extensionName = $this->arguments['extensionName'];
@@ -102,7 +217,7 @@ final class ActionViewHelper extends AbstractTagBasedViewHelper
         $argumentsToBeExcludedFromQueryString = (array)$this->arguments['argumentsToBeExcludedFromQueryString'];
         $parameters = $this->arguments['arguments'];
 
-        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
+        $uriBuilder = GeneralUtility::makeInstance(ExtbaseUriBuilder::class);
         $uriBuilder
             ->reset()
             ->setRequest($request)
@@ -121,7 +236,6 @@ final class ActionViewHelper extends AbstractTagBasedViewHelper
         if (MathUtility::canBeInterpretedAsInteger($pageUid)) {
             $uriBuilder->setTargetPageUid((int)$pageUid);
         }
-
         $uri = $uriBuilder->uriFor($action, $parameters, $controller, $extensionName, $pluginName);
         if ($uri === '') {
             return $this->renderChildren();
diff --git a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/ActionViewHelper.php b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/ActionViewHelper.php
index 3fd0a9b3d96817f6774818710b23c19c368779ea..42e042fc79d979bf9ff3de869a2fc5ffc030e1d1 100644
--- a/typo3/sysext/fluid/Classes/ViewHelpers/Uri/ActionViewHelper.php
+++ b/typo3/sysext/fluid/Classes/ViewHelpers/Uri/ActionViewHelper.php
@@ -17,10 +17,16 @@ declare(strict_types=1);
 
 namespace TYPO3\CMS\Fluid\ViewHelpers\Uri;
 
+use Psr\Http\Message\ServerRequestInterface;
+use TYPO3\CMS\Core\Http\ApplicationType;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Mvc\RequestInterface;
-use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
+use TYPO3\CMS\Core\Utility\HttpUtility;
+use TYPO3\CMS\Extbase\Mvc\RequestInterface as ExtbaseRequestInterface;
+use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder as ExtbaseUriBuilder;
 use TYPO3\CMS\Fluid\Core\Rendering\RenderingContext;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\Typolink\LinkFactory;
+use TYPO3\CMS\Frontend\Typolink\UnableToLinkException;
 use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
 use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
 use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
@@ -67,16 +73,124 @@ final class ActionViewHelper extends AbstractViewHelper
     {
         /** @var RenderingContext $renderingContext */
         $request = $renderingContext->getRequest();
-        if (!$request instanceof RequestInterface) {
+        if ($request instanceof ExtbaseRequestInterface) {
+            return self::renderWithExtbaseContext($request, $arguments);
+        }
+
+        if ($request instanceof ServerRequestInterface && ApplicationType::fromRequest($request)->isFrontend()) {
+            return self::renderFrontendLinkWithCoreContext($request, $arguments, $renderChildrenClosure);
+        }
+        throw new \RuntimeException(
+            'The rendering context of ViewHelper f:uri.action is missing a valid request object.',
+            1690360598
+        );
+    }
+
+    protected static function renderFrontendLinkWithCoreContext(ServerRequestInterface $request, array $arguments, \Closure $renderChildrenClosure): string
+    {
+        // No support for following arguments:
+        //  * format
+        $pageUid = (int)($arguments['pageUid'] ?? 0);
+        $pageType = (int)($arguments['pageType'] ?? 0);
+        $noCache = (bool)($arguments['noCache'] ?? false);
+        /** @var string|null $language */
+        $language = $arguments['language'] ?? null;
+        /** @var string|null $section */
+        $section = $arguments['section'] ?? null;
+        $linkAccessRestrictedPages = (bool)($arguments['linkAccessRestrictedPages'] ?? false);
+        /** @var array|null $additionalParams */
+        $additionalParams = $arguments['additionalParams'] ?? null;
+        $absolute = (bool)($arguments['absolute'] ?? false);
+        /** @var bool|string $addQueryString */
+        $addQueryString = $arguments['addQueryString'] ?? false;
+        /** @var array|null $argumentsToBeExcludedFromQueryString */
+        $argumentsToBeExcludedFromQueryString = $arguments['argumentsToBeExcludedFromQueryString'] ?? null;
+        /** @var string|null $action */
+        $action = $arguments['action'] ?? null;
+        /** @var string|null $controller */
+        $controller = $arguments['controller'] ?? null;
+        /** @var string|null $extensionName */
+        $extensionName = $arguments['extensionName'] ?? null;
+        /** @var string|null $pluginName */
+        $pluginName = $arguments['pluginName'] ?? null;
+        /** @var array|null $arguments */
+        $arguments = $arguments['arguments'] ?? [];
+
+        $allExtbaseArgumentsAreSet = (
+            is_string($extensionName) && $extensionName !== ''
+            && is_string($pluginName) && $pluginName !== ''
+            && is_string($controller) && $controller !== ''
+            && is_string($action) && $action !== ''
+        );
+        if (!$allExtbaseArgumentsAreSet) {
             throw new \RuntimeException(
-                'ViewHelper f:uri.action can be used only in extbase context and needs a request implementing extbase RequestInterface.',
+                'ViewHelper f:uri.action needs either all extbase arguments set'
+                . ' ("extensionName", "pluginName", "controller", "action")'
+                . ' or needs a request implementing extbase RequestInterface.',
                 1639819692
             );
         }
 
+        // Provide extbase default and custom arguments as prefixed additional params
+        $extbaseArgumentNamespace = 'tx_'
+            . str_replace('_', '', strtolower($extensionName))
+            . '_'
+            . str_replace('_', '', strtolower($pluginName));
+        $additionalParams ??= [];
+        $additionalParams[$extbaseArgumentNamespace] = array_replace(
+            [
+                'controller' => $controller,
+                'action' => $action,
+            ],
+            $arguments
+        );
+
+        $typolinkConfiguration = [
+            'parameter' => $pageUid,
+        ];
+        if ($pageType) {
+            $typolinkConfiguration['parameter'] .= ',' . $pageType;
+        }
+        if ($language !== null) {
+            $typolinkConfiguration['language'] = $language;
+        }
+        if ($noCache) {
+            $typolinkConfiguration['no_cache'] = 1;
+        }
+        if ($section) {
+            $typolinkConfiguration['section'] = $section;
+        }
+        if ($linkAccessRestrictedPages) {
+            $typolinkConfiguration['linkAccessRestrictedPages'] = 1;
+        }
+        $typolinkConfiguration['additionalParams'] = HttpUtility::buildQueryString($additionalParams, '&');
+        if ($absolute) {
+            $typolinkConfiguration['forceAbsoluteUrl'] = true;
+        }
+        if ($addQueryString && $addQueryString !== 'false') {
+            $typolinkConfiguration['addQueryString'] = $addQueryString;
+            if ($argumentsToBeExcludedFromQueryString !== []) {
+                $typolinkConfiguration['addQueryString.']['exclude'] = implode(',', $argumentsToBeExcludedFromQueryString);
+            }
+        }
+
+        try {
+            $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
+            $cObj->setRequest($request);
+            $linkFactory = GeneralUtility::makeInstance(LinkFactory::class);
+            $linkResult = $linkFactory->create((string)$renderChildrenClosure(), $typolinkConfiguration, $cObj);
+            return $linkResult->getUrl();
+        } catch (UnableToLinkException) {
+            return (string)$renderChildrenClosure();
+        }
+    }
+
+    protected static function renderWithExtbaseContext(ExtbaseRequestInterface $request, array $arguments): string
+    {
         $pageUid = (int)($arguments['pageUid'] ?? 0);
         $pageType = (int)($arguments['pageType'] ?? 0);
         $noCache = (bool)($arguments['noCache'] ?? false);
+        /** @var string|null $language */
         $language = $arguments['language'] ?? null;
         /** @var string|null $section */
         $section = $arguments['section'] ?? null;
@@ -101,9 +215,10 @@ final class ActionViewHelper extends AbstractViewHelper
         /** @var array|null $arguments */
         $arguments = $arguments['arguments'] ?? [];
 
-        /** @var UriBuilder $uriBuilder */
-        $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
-        $uriBuilder->reset()->setRequest($request);
+        /** @var ExtbaseUriBuilder $uriBuilder */
+        $uriBuilder = GeneralUtility::makeInstance(ExtbaseUriBuilder::class);
+        $uriBuilder->reset();
+        $uriBuilder->setRequest($request);
 
         if ($pageUid > 0) {
             $uriBuilder->setTargetPageUid($pageUid);
diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Link/ActionViewHelperTest.php b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Link/ActionViewHelperTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..52146f016ddd7125f0bd4356d45769425ebb035f
--- /dev/null
+++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Link/ActionViewHelperTest.php
@@ -0,0 +1,232 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Link;
+
+use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
+use TYPO3\CMS\Core\Domain\Repository\PageRepository;
+use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Routing\PageArguments;
+use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
+use TYPO3\CMS\Core\TypoScript\AST\Node\RootNode;
+use TYPO3\CMS\Core\TypoScript\FrontendTypoScript;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters;
+use TYPO3\CMS\Extbase\Mvc\Request;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+final class ActionViewHelperTest extends FunctionalTestCase
+{
+    use SiteBasedTestTrait;
+
+    protected const LANGUAGE_PRESETS = [
+        'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
+    ];
+
+    protected array $configurationToUseInTestInstance = [
+        'FE' => [
+            'cacheHash' => [
+                'excludedParameters' => [
+                    'untrusted',
+                ],
+            ],
+        ],
+    ];
+
+    /**
+     * @test
+     */
+    public function renderThrowsExceptionWithoutARequest(): void
+    {
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1690365240);
+        $view = new StandaloneView();
+        $view->setRequest();
+        $view->setTemplateSource('<f:link.action />');
+        $view->render();
+    }
+
+    /**
+     * @test
+     */
+    public function renderInFrontendCoreContextThrowsExceptionWithIncompleteArguments(): void
+    {
+        $request = new ServerRequest();
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE);
+        $request = $request->withAttribute('routing', new PageArguments(1, '0', []));
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1690370264);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource('<f:link.action />');
+        $view->render();
+    }
+
+    /**
+     * @test
+     */
+    public function renderInBackendCoreContextThrowsExceptionWithIncompleteArguments(): void
+    {
+        $request = new ServerRequest('http://localhost/typo3/');
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE);
+        $request = $request->withQueryParams(['route' => 'web_layout']);
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1690365240);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource('<f:link.action />');
+        $view->render();
+    }
+
+    public static function renderInFrontendWithCoreContextAndAllNecessaryExtbaseArgumentsDataProvider(): \Generator
+    {
+        yield 'link to root page with plugin' => [
+            '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link to root page with plugin</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with plugin</a>',
+        ];
+
+        yield 'link to root page with plugin and section' => [
+            '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" section="c13">link to root page with plugin and section</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c#c13">link to root page with plugin and section</a>',
+        ];
+
+        yield 'link to root page with page type' => [
+            '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" pageType="1234">link to root page with page type</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with page type</a>',
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider renderInFrontendWithCoreContextAndAllNecessaryExtbaseArgumentsDataProvider
+     */
+    public function renderInFrontendWithCoreContextAndAllNecessaryExtbaseArguments(string $template, string $expected): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/../../Fixtures/pages.csv');
+        $this->writeSiteConfiguration(
+            'test',
+            $this->buildSiteConfiguration(1, '/'),
+        );
+        $request = new ServerRequest();
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE);
+        $request = $request->withAttribute('routing', new PageArguments(1, '0', ['untrusted' => 123]));
+        $GLOBALS['TYPO3_REQUEST'] = $request;
+        $GLOBALS['TSFE'] = $this->createMock(TypoScriptFrontendController::class);
+        $GLOBALS['TSFE']->id = 1;
+        $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource($template);
+        $result = $view->render();
+        self::assertSame($expected, $result);
+    }
+
+    public static function renderInFrontendWithExtbaseContextDataProvider(): \Generator
+    {
+        // with all extbase arguments provided
+        yield 'link to root page with plugin' => [
+            '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show">link to root page with plugin</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with plugin</a>',
+        ];
+
+        yield 'link to root page with plugin and section' => [
+            '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" section="c13">link to root page with plugin and section</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c#c13">link to root page with plugin and section</a>',
+        ];
+
+        yield 'link to root page with page type' => [
+            '<f:link.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" pageType="1234">link to root page with page type</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c">link to root page with page type</a>',
+        ];
+        // without all extbase arguments provided
+        yield 'renderProvidesATagForValidLinkTarget' => [
+            '<f:link.action>index.php</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3">index.php</a>',
+        ];
+        yield 'renderWillProvideEmptyATagForNonValidLinkTarget' => [
+            '<f:link.action></f:link.action>',
+            '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3"></a>',
+        ];
+        yield 'link to root page in extbase context' => [
+            '<f:link.action pageUid="1">linkMe</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3">linkMe</a>',
+        ];
+        yield 'link to root page with section' => [
+            '<f:link.action pageUid="1" section="c13">linkMe</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3#c13">linkMe</a>',
+        ];
+        yield 'link to root page with page type in extbase context' => [
+            '<f:link.action pageUid="1" pageType="1234">linkMe</f:link.action>',
+            '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3">linkMe</a>',
+        ];
+        yield 'link to root page with untrusted query arguments' => [
+            '<f:link.action addQueryString="untrusted"></f:link.action>',
+            '<a href="/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;untrusted=123&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3"></a>',
+        ];
+        yield 'link to page sub page' => [
+            '<f:link.action pageUid="3">linkMe</f:link.action>',
+            '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=d9289022f99f8cbc8080832f61e46509">linkMe</a>',
+        ];
+        yield 'arguments one level' => [
+            '<f:link.action pageUid="3" arguments="{foo: \'bar\'}">haiku title</f:link.action>',
+            '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Bcontroller%5D=Detail&amp;tx_examples_haiku%5Bfoo%5D=bar&amp;cHash=74dd4635cee85b19b67cd9b497ec99e9">haiku title</a>',
+        ];
+        yield 'additional parameters two levels' => [
+            '<f:link.action pageUid="3" additionalParams="{tx_examples_haiku: {action: \'show\', haiku: 42}}">haiku title</f:link.action>',
+            '<a href="/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;tx_examples_haiku%5Bhaiku%5D=42&amp;cHash=aefc37bc2323ebd8c8e39c222adb7413">haiku title</a>',
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider renderInFrontendWithExtbaseContextDataProvider
+     */
+    public function renderInFrontendWithExtbaseContext(string $template, string $expected): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/../../Fixtures/pages.csv');
+        $this->writeSiteConfiguration(
+            'test',
+            $this->buildSiteConfiguration(1, '/'),
+        );
+        $frontendTypoScript = new FrontendTypoScript(new RootNode(), []);
+        $frontendTypoScript->setSetupArray([]);
+        $extbaseRequestParameters = new ExtbaseRequestParameters();
+        $extbaseRequestParameters->setControllerExtensionName('Examples');
+        $extbaseRequestParameters->setControllerName('Detail');
+        $extbaseRequestParameters->setControllerActionName('show');
+        $extbaseRequestParameters->setPluginName('Haiku');
+        $request = new ServerRequest();
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE);
+        $request = $request->withAttribute('routing', new PageArguments(1, '0', ['untrusted' => 123]));
+        $request = $request->withAttribute('extbase', $extbaseRequestParameters);
+        $request = $request->withAttribute('currentContentObject', $this->get(ContentObjectRenderer::class));
+        $request = $request->withAttribute('frontend.typoscript', $frontendTypoScript);
+        $request = new Request($request);
+        $GLOBALS['TYPO3_REQUEST'] = $request;
+        $GLOBALS['TSFE'] = $this->createMock(TypoScriptFrontendController::class);
+        $GLOBALS['TSFE']->id = 1;
+        $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource($template);
+        $result = $view->render();
+        self::assertSame($expected, $result);
+    }
+}
diff --git a/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Uri/ActionViewHelperTest.php b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Uri/ActionViewHelperTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..96a2d61d7351375fb1010f31e0a17c07b3132057
--- /dev/null
+++ b/typo3/sysext/fluid/Tests/Functional/ViewHelpers/Uri/ActionViewHelperTest.php
@@ -0,0 +1,228 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Fluid\Tests\Functional\ViewHelpers\Uri;
+
+use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder;
+use TYPO3\CMS\Core\Domain\Repository\PageRepository;
+use TYPO3\CMS\Core\Http\ServerRequest;
+use TYPO3\CMS\Core\Routing\PageArguments;
+use TYPO3\CMS\Core\Tests\Functional\SiteHandling\SiteBasedTestTrait;
+use TYPO3\CMS\Core\TypoScript\AST\Node\RootNode;
+use TYPO3\CMS\Core\TypoScript\FrontendTypoScript;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Extbase\Mvc\ExtbaseRequestParameters;
+use TYPO3\CMS\Extbase\Mvc\Request;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
+use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
+use TYPO3\TestingFramework\Core\Functional\FunctionalTestCase;
+
+final class ActionViewHelperTest extends FunctionalTestCase
+{
+    use SiteBasedTestTrait;
+
+    protected const LANGUAGE_PRESETS = [
+        'EN' => ['id' => 0, 'title' => 'English', 'locale' => 'en_US.UTF8'],
+    ];
+
+    protected array $configurationToUseInTestInstance = [
+        'FE' => [
+            'cacheHash' => [
+                'excludedParameters' => [
+                    'untrusted',
+                ],
+            ],
+        ],
+    ];
+
+    /**
+     * @test
+     */
+    public function renderThrowsExceptionWithoutARequest(): void
+    {
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1690360598);
+        $view = new StandaloneView();
+        $view->setRequest();
+        $view->setTemplateSource('<f:uri.action />');
+        $view->render();
+    }
+
+    /**
+     * @test
+     */
+    public function renderInFrontendCoreContextThrowsExceptionWithIncompleteArguments(): void
+    {
+        $request = new ServerRequest();
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE);
+        $request = $request->withAttribute('routing', new PageArguments(1, '0', []));
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1639819692);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource('<f:uri.action />');
+        $view->render();
+    }
+
+    /**
+     * @test
+     */
+    public function renderInBackendCoreContextThrowsExceptionWithIncompleteArguments(): void
+    {
+        $request = new ServerRequest('http://localhost/typo3/');
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_BE);
+        $request = $request->withQueryParams(['route' => 'web_layout']);
+        $this->expectException(\RuntimeException::class);
+        $this->expectExceptionCode(1690360598);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource('<f:uri.action />');
+        $view->render();
+    }
+
+    public static function renderInFrontendWithCoreContextAndAllNecessaryExtbaseArgumentsDataProvider(): \Generator
+    {
+        yield 'link to root page with plugin' => [
+            '<f:uri.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" />',
+            '/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c',
+        ];
+
+        yield 'link to root page with plugin and section' => [
+            '<f:uri.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" section="c13" />',
+            '/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c#c13',
+        ];
+
+        yield 'link to root page with page type' => [
+            '<f:uri.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" pageType="1234" />',
+            '/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c',
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider renderInFrontendWithCoreContextAndAllNecessaryExtbaseArgumentsDataProvider
+     */
+    public function renderInFrontendWithCoreContextAndAllNecessaryExtbaseArguments(string $template, string $expected): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/../../Fixtures/pages.csv');
+        $this->writeSiteConfiguration(
+            'test',
+            $this->buildSiteConfiguration(1, '/'),
+        );
+        $request = new ServerRequest();
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE);
+        $request = $request->withAttribute('routing', new PageArguments(1, '0', ['untrusted' => 123]));
+        $GLOBALS['TYPO3_REQUEST'] = $request;
+        $GLOBALS['TSFE'] = $this->createMock(TypoScriptFrontendController::class);
+        $GLOBALS['TSFE']->id = 1;
+        $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource($template);
+        $result = $view->render();
+        self::assertSame($expected, $result);
+    }
+
+    public static function renderInFrontendWithExtbaseContextDataProvider(): \Generator
+    {
+        // with all extbase arguments provided
+        yield 'link to root page with plugin' => [
+            '<f:uri.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" />',
+            '/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c',
+        ];
+
+        yield 'link to root page with plugin and section' => [
+            '<f:uri.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" section="c13" />',
+            '/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c#c13',
+        ];
+
+        yield 'link to root page with page type' => [
+            '<f:uri.action pageUid="1" extensionName="examples" pluginName="haiku" controller="Detail" action="show" pageType="1234" />',
+            '/?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=5c6aa07f6ceee30ae2ea8dbf574cf26c',
+        ];
+        // without all extbase arguments provided
+        yield 'renderWillProvideEmptyATagForNonValidLinkTarget' => [
+            '<f:uri.action />',
+            '/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3',
+        ];
+        yield 'link to root page in extbase context' => [
+            '<f:uri.action pageUid="1" />',
+            '/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3',
+        ];
+        yield 'link to root page with section' => [
+            '<f:uri.action pageUid="1" section="c13" />',
+            '/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3#c13',
+        ];
+        yield 'link to root page with page type in extbase context' => [
+            '<f:uri.action pageUid="1" pageType="1234" />',
+            '/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;type=1234&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3',
+        ];
+        yield 'link to root page with untrusted query arguments' => [
+            '<f:uri.action addQueryString="untrusted" />',
+            '/?tx_examples_haiku%5Bcontroller%5D=Detail&amp;untrusted=123&amp;cHash=1d5a12de6bf2d5245b654deb866ee9c3',
+        ];
+        yield 'link to page sub page' => [
+            '<f:uri.action pageUid="3" />',
+            '/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Bcontroller%5D=Detail&amp;cHash=d9289022f99f8cbc8080832f61e46509',
+        ];
+        yield 'arguments one level' => [
+            '<f:uri.action pageUid="3" arguments="{foo: \'bar\'}" />',
+            '/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Bcontroller%5D=Detail&amp;tx_examples_haiku%5Bfoo%5D=bar&amp;cHash=74dd4635cee85b19b67cd9b497ec99e9',
+        ];
+        yield 'additional parameters two levels' => [
+            '<f:uri.action pageUid="3" additionalParams="{tx_examples_haiku: {action: \'show\', haiku: 42}}" />',
+            '/dummy-1-2/dummy-1-2-3?tx_examples_haiku%5Baction%5D=show&amp;tx_examples_haiku%5Bcontroller%5D=Detail&amp;tx_examples_haiku%5Bhaiku%5D=42&amp;cHash=aefc37bc2323ebd8c8e39c222adb7413',
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider renderInFrontendWithExtbaseContextDataProvider
+     */
+    public function renderInFrontendWithExtbaseContext(string $template, string $expected): void
+    {
+        $this->importCSVDataSet(__DIR__ . '/../../Fixtures/pages.csv');
+        $this->writeSiteConfiguration(
+            'test',
+            $this->buildSiteConfiguration(1, '/'),
+        );
+        $frontendTypoScript = new FrontendTypoScript(new RootNode(), []);
+        $frontendTypoScript->setSetupArray([]);
+        $extbaseRequestParameters = new ExtbaseRequestParameters();
+        $extbaseRequestParameters->setControllerExtensionName('Examples');
+        $extbaseRequestParameters->setControllerName('Detail');
+        $extbaseRequestParameters->setControllerActionName('show');
+        $extbaseRequestParameters->setPluginName('Haiku');
+        $request = new ServerRequest();
+        $request = $request->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE);
+        $request = $request->withAttribute('routing', new PageArguments(1, '0', ['untrusted' => 123]));
+        $request = $request->withAttribute('extbase', $extbaseRequestParameters);
+        $request = $request->withAttribute('currentContentObject', $this->get(ContentObjectRenderer::class));
+        $request = $request->withAttribute('frontend.typoscript', $frontendTypoScript);
+        $request = new Request($request);
+        $GLOBALS['TYPO3_REQUEST'] = $request;
+        $GLOBALS['TSFE'] = $this->createMock(TypoScriptFrontendController::class);
+        $GLOBALS['TSFE']->id = 1;
+        $GLOBALS['TSFE']->sys_page = GeneralUtility::makeInstance(PageRepository::class);
+        $view = new StandaloneView();
+        $view->setRequest($request);
+        $view->setTemplateSource($template);
+        $result = $view->render();
+        self::assertSame($expected, $result);
+    }
+}