Answers.Body: <p>I think <a href="https://craftcms.stackexchange.com/a/38324/4169">my other answer</a> is also part of this one.</p>
  <p>The only specifics I'd add here is that your action is getting &quot;double-declared,&quot; in a way. Using the <code>action</code> param in a request has a lot of weight in Craft's eye—but you're stacking two strategies, and the system can't match it with your intent.</p>
  <p>My recommendation is (whenever possible) to use Craft's Twig helpers:</p>
  <pre><code>&lt;form method=&quot;POST&quot;&gt;
      {{ csrfInput() }}
      {{ actionInput('mapit-api2entry/default/map-it') }}
  
      &lt;button&gt;Go!&lt;/button&gt;
  &lt;/form&gt;
  </code></pre>
  <p>This will generate a hidden <code>action</code> input that looks like this:</p>
  <pre class="lang-html prettyprint-override"><code>&lt;input name=&quot;action&quot; value=&quot;mapit-api2entry/default/map-it&quot;&gt;
  </code></pre>
  <p>Notice that we don't declare <code>action</code> as part of the route! Craft already knows you want to route directly to a Controller/Action path because it sees the <code>action</code> param.</p>
  <p>The direct-access behavior you see is a vanity/convenience feature—the <a href="https://craftcms.com/docs/3.x/config/config-settings.html#actiontrigger" rel="nofollow noreferrer"><code>actionTrigger</code></a> (the first segment in that path, aside from the <a href="https://craftcms.com/docs/3.x/config/config-settings.html#cptrigger" rel="nofollow noreferrer"><code>cpTrigger</code></a>—<code>admin</code> by default) is actually customizable, and not particularly useful in my mind, when the Twig helpers (and <code>action</code> query/POST param) are so reliable.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-09-15T15:15:37.397Z
Answers.Text: Thanks for taking the time to reply.(lovely work by the way )
  Finally got a result.
  So is there no need to tell craft that this is a cptrigger - is this done in the route?   $event->rules['mapit-api2entry/default/map-it'] = 'results';
  And or in the controller? Eg $this->renderTemplate('xxx')
Answers.UserDisplayName: joomkit
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-09-16T16:46:01.450Z
Answers.Text: Keep in mind that the "key" you assign to the `rules` array is the alias to your controller action, and the "value" (what is assigned) is the full controller path: `$event->rules['my-shortcut-route'] = 'mapit-api2entry/default/map-it';`, where `DefaultController::actionMapIt()` becomes available at `my-shortcut-route` (or `admin/my-shortcut-route`, if you're in the CP). I'm not entirely sure how the determinations of an "Action Request" and a "CP Request" overlap—but generally, actions are for logic + processing, and they redirect to an `admin/my-route` in success/fail states.
Answers.UserDisplayName: August Miller
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-09-15T03:47:27.727Z
Answers.LastActivityDate: 2021-09-15T03:47:27.727Z
Answers.UserDisplayName: August Miller
Body: <p>I have a plugin that has a menu and in backend which basically has a button that calls the plugins default controller actionXXXX method.</p>
  <p>The action does some database / api work then is meant to return a result in a results template.</p>
  <p>I have no idea how plugins got so complicated in craft and Im about ready to give up after today. The plugin main file supplies EVENT_REGISTER_CP_URL_RULES</p>
  <pre><code> Event::on(
              UrlManager::class,
              UrlManager::EVENT_REGISTER_CP_URL_RULES,
              function (RegisterUrlRulesEvent $event) {
                  $event-&gt;rules['mapit-api2entry/default/map-it'] = 'results';
              }
          );
  </code></pre>
  <p>The plugin form in the cp has a hidden action like so. Do I need admin here? I assume so because we are in the CP.</p>
  <pre><code>&lt;input type=&quot;hidden&quot; name=&quot;action&quot; value=&quot;admin/actions/mapit-api2entry/default/map-it&quot;&gt;
  </code></pre>
  <p>I can put the url &quot;admin/actions/mapit-api2entry/default/map-it&quot; in the browser and pull up my template as expected.</p>
  <p>But when I hit the submit button I get:</p>
  <pre><code>Unable to resolve the request &quot;admin/actions/mapit-api2entry/default/map-it&quot;.
  </code></pre>
  <p>How do I tell the plugin / cp the right route to use after the action is triggered? Is this case of camel -vs kebab somewhere?</p>
  
Tags: <plugin-development><control-panel><routes>
Title: Why do i get an Invalid route error in cp when calling plugin action?
ThreadText: # Why do i get an Invalid route error in cp when calling plugin action?
  
  (Asked by: username_0 on 2021-09-14)
  
  I have a plugin that has a menu and in backend which basically has a button that calls the plugins default controller actionXXXX method.
  
  The action does some database / api work then is meant to return a result in a results template.
  
  I have no idea how plugins got so complicated in craft and Im about ready to give up after today. The plugin main file supplies EVENT\_REGISTER\_CP\_URL\_RULES
  
  ```
   Event::on(
              UrlManager::class,
              UrlManager::EVENT_REGISTER_CP_URL_RULES,
              function (RegisterUrlRulesEvent $event) {
                  $event->rules['mapit-api2entry/default/map-it'] = 'results';
              }
          );
  
  ```
  
  The plugin form in the cp has a hidden action like so. Do I need admin here? I assume so because we are in the CP.
  
  ```
  <input type="hidden" name="action" value="admin/actions/mapit-api2entry/default/map-it">
  
  ```
  
  I can put the url "admin/actions/mapit-api2entry/default/map-it" in the browser and pull up my template as expected.
  
  But when I hit the submit button I get:
  
  ```
  Unable to resolve the request "admin/actions/mapit-api2entry/default/map-it".
  
  ```
  
  How do I tell the plugin / cp the right route to use after the action is triggered? Is this case of camel -vs kebab somewhere?
  
  **Tags:** plugin-development, control-panel, routes
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2021-09-15. Score: 3 | Accepted answer
  
  I think [my other answer](https://craftcms.stackexchange.com/a/38324/4169) is also part of this one.
  
  The only specifics I'd add here is that your action is getting "double-declared," in a way. Using the `action` param in a request has a lot of weight in Craft's eye—but you're stacking two strategies, and the system can't match it with your intent.
  
  My recommendation is (whenever possible) to use Craft's Twig helpers:
  
  ```
  <form method="POST">
      {{ csrfInput() }}
      {{ actionInput('mapit-api2entry/default/map-it') }}
  
      <button>Go!</button>
  </form>
  
  ```
  
  This will generate a hidden `action` input that looks like this:
  
  ```html
  <input name="action" value="mapit-api2entry/default/map-it">
  
  ```
  
  Notice that we don't declare `action` as part of the route! Craft already knows you want to route directly to a Controller/Action path because it sees the `action` param.
  
  The direct-access behavior you see is a vanity/convenience feature—the [`actionTrigger`](https://craftcms.com/docs/3.x/config/config-settings.html#actiontrigger) (the first segment in that path, aside from the [`cpTrigger`](https://craftcms.com/docs/3.x/config/config-settings.html#cptrigger)—`admin` by default) is actually customizable, and not particularly useful in my mind, when the Twig helpers (and `action` query/POST param) are so reliable.
  
  > **Comments:**
  > **username_0**: Thanks for taking the time to reply.(lovely work by the way ) Finally got a result. So is there no need to tell craft that this is a cptrigger - is this done in the route?   $event->rules['mapit-api2entry/default/map-it'] = 'results'; And or in the controller? Eg $this->renderTemplate('xxx')  
  > **username_1**: Keep in mind that the "key" you assign to the `rules` array is the alias to your controller action, and the "value" (what is assigned) is the full controller path: `$event->rules['my-shortcut-route'] = 'mapit-api2entry/default/map-it';`, where `DefaultController::actionMapIt()` becomes available at `my-shortcut-route` (or `admin/my-shortcut-route`, if you're in the CP). I'm not entirely sure how the determinations of an "Action Request" and a "CP Request" overlap—but generally, actions are for logic + processing, and they redirect to an `admin/my-route` in success/fail states.  
  
  ---
  
  