external form problems after 8.5.4 upgrade

I've recently upgraded a site to C5 8.5.4 from 8.4.3 and am now having trouble with some external forms. Oddly some external forms still seem to work but others don't.

Using, for example, the test form view:

$form = Loader::helper('form');
defined('C5_EXECUTE') or die("Access Denied.");
if (isset($response)) { ?>
   <div class="alert alert-info"><?php echo $response?></div>
<?php } ?>
<form method="post" action="<?php echo $view->action('test_search')?>">
    <p><?php echo $message?></p>
    <div class="form-group">
        <label class="control-label"><?php echo t('Test')?></label>
        <?php echo $form->text('test_text_field')?>
    <div class="form-group">
        <input type="submit" name="submit" value="submit" class="btn btn-default" />

and the test form controller:

namespace Application\Block\ExternalForm\Form\Controller;
use Concrete\Core\Controller\AbstractController;
class TestForm extends AbstractController
    public function action_test_search($bID = false)
        if ($this->bID == $bID) {
            $this->set('response', t('Thanks!'));
            return true;
    public function view()
        $this->set('message', t('This is just an example of how a custom form works.'));

When I add the external form block to a page and submit the form I get a url like:


and the message 'Access Denied'. I traced this through to the 'edit' method of Concrete\Controller\Backend\Block\Action

public function edit($cID, $arHandle, $bID, $action)
        $c = \Page::getByID($cID);
        if (is_object($c) && !$c->isError()) {
            $a = \Area::getOrCreate($c, $arHandle);
            $ax = $a;
            $cx = $c;
            if ($a->isGlobalArea()) {
                $cx = \Stack::getByName($arHandle);
                $ax = \Area::get($cx, STACKS_AREA_NAME);
            $b = \Block::getByID($bID, $cx, $ax);
            if (is_object($b)) {
                $controller = $b->getController();

On form submission, this method is passed the variables in the url:
cID: 1 arHandle: Main bID: 77513 action: test_search

The if block with validateEditBlockPassThruAction($b) fails because the 'guests' group does not have edit permissions on the block and I end up seeing the 'Access Denied' response. I checked the 8.4.3 version of this method and it has the same validateEditBlockPassThruAction($b) check, though I've never had to allow guest edit permissions on an external form block before. If I do set guest edit permissions on the block and submit the form then the $this->deliverResponse() line is run and the action_test_search method is run in the external form controller except that the bID is not passed in so nothing happens.

Looking for 8.5.4 issues on github I saw thishttps://github.com/concrete5/concrete5/issues/8771.... I ran `concrete/bin/concrete5 migrations:status` and it seems like the migrations are up to date at

>> Current Version: 2020-06-09 14:53:07 (20200609145307)

All the tables in the database have the right character set and collation but I do have a lot (+1500) of columns in the C5 database with NULL character sets and collations. Could that even affect external forms and should I try to alter the character set and collation of these columns?

View Replies:
hutman replied on at Permalink Reply
When you say "submit the form" are you clicking submit on the edit dialog, or are you clicking submit on the page when you are logged out?

Do you have caching turned on? If so, does this issue persist if you turn it off and clear the cache?
dennismoore replied on at Permalink Reply
By "submit the form" I mean clicking the submit button of the form while not logged in. Caching is off and I've tried clearing cache but the problem persists.

I spun up an 8.4.3 version of the site and the test form works fine there. I noticed that the result of $view->action('test_search') is different between the two:

8.5.4 => /ccm/system/block/action/edit/316/ColumnRightTop/77512/test_search
8.4.3 => /page-name/test_search/80115

I've found a fix that basically involves commenting out the line:

return call_user_func_array([$this->controller, 'getActionURL'], func_get_args());

in Concrete\Core\Block\View\BlockView::action and pasting in the 8.4.3 version of that method.
Not pretty but beats having all the forms broken.

That logic seems to have been moved to Concrete\Core\Block\BlockController::getActionURL($task) and although the action 'test_search' is passed in as $task, the method calls $this->getAction() to set the action which appears to end up calling the method on the AbstractController. That is coming back blank, so it falls through to the else block and returns the edit url.

So maybe the action property of the AbstractController isn't being set somewhere? I haven't noticed where that happens yet.