Answers.Body: <p>It depends on the module handle you chose in <em>config/app.php</em> (the module handle is the key affected to your module in the <code>modules</code> array).</p>
  <p>If you want the URL to be <code>/business-logic/example/example-route</code>, the module key must be <code>business-logic</code>:</p>
  <pre class="lang-php prettyprint-override"><code>use modules\businesslogic\BusinessLogic;
  
  return [
      'modules' =&gt; [
          'business-logic' =&gt; BusinessLogic::class,
      ],
      'bootstrap' =&gt; [
          'business-logic',
      ]
  ];
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-03-03T11:10:44.887Z
Answers.LastActivityDate: 2021-03-03T11:10:44.887Z
Answers.UserDisplayName: nstCactus
Answers.Body: <p>Whenever I'm using controllers for direct URL access (e.g. from JavaScript via an XHR or fetch request), I've accessed them using a query string rather than relying on rewritten URLs. So, like this:</p>
  <pre><code>https://my-craft-site/index.php?p=actions/business-logic/example/example-route
  </code></pre>
  <p>If the controller method is intended to be triggered from a form submit, you can just use the <code>actionInput</code> Twig function:</p>
  <pre><code>&lt;form method=&quot;post&quot;&gt;
     {{ actionInput('business-logic/example/example-route') }}
  
     {# Some form input fields here... #}
  
      &lt;button type=&quot;submit&quot;&gt;
  &lt;/form&gt;
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-03-03T09:50:30.080Z
Answers.LastActivityDate: 2021-03-03T09:50:30.080Z
Answers.UserDisplayName: Martin Spain
Answers.Body: <p>The cause of the issue turned out to be an incorrect controllerNamespace reference in the <a href="https://github.com/doublesecretagency/craft-businesslogic" rel="nofollow noreferrer">Business Logic Template</a> example. If anyone else is using the example project to jumpstart a Craft module, be aware of the following:</p>
  <p>In that example, the ExampleController.php controller specifies this namespace...</p>
  <pre><code>namespace modules\businesslogic\controllers;
  </code></pre>
  <p>...but BusinessLogic.php sets the controllerNameSpace like this, (note that it's missing <strong>modules\</strong>)...</p>
  <pre><code>// Adjust controller namespace for console requests
  if (Craft::$app-&gt;getRequest()-&gt;getIsConsoleRequest()) {
      $this-&gt;controllerNamespace = 'businesslogic\\console\\controllers';
  }
  </code></pre>
  <p>...it worked for me after I changed it to match the ExampleController namespace, (note the addition of <strong>modules\</strong> as well as handling both console and web requests)...</p>
  <pre><code>// Adjust controller namespace for console requests
  if (Craft::$app-&gt;getRequest()-&gt;getIsConsoleRequest()) {
      $this-&gt;controllerNamespace = 'modules\\businesslogic\\console\\controllers';
  } else {
      $this-&gt;controllerNamespace = 'modules\\businesslogic\\controllers';
  }
  </code></pre>
  <p><strong>EDIT</strong></p>
  <p>To answer my own original question, the correct way to call the module action is:</p>
  <pre><code>http://my-craft-site/actions/businesslogic/example/example-route
  </code></pre>
  <p>Note that <strong>/actions</strong> precedes the <em>module/controller/action</em> portion of the URL, and that the controller and action are <a href="https://en.wiktionary.org/wiki/kebab_case" rel="nofollow noreferrer">kebab-cased</a>. As @nstCactus points out, the module is the module handle defined in <em>config/app.php</em>.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2021-03-03T16:37:01.903Z
Answers.LastActivityDate: 2021-03-03T20:57:44.870Z
Answers.LastEditDate: 2021-03-03T20:57:44.870Z
Answers.UserDisplayName: Dan Madoni
Body: <p>Consider the following Craft 3 example module structure:</p>
  <pre><code>modules/
      businesslogic/
          controllers/ExampleController.php
          BusinessLogic.php
  </code></pre>
  <p>...and consider the following action in ExampleController.php:</p>
  <pre><code>public function actionExampleRoute()
  {
      die('in example-route action');
  }
  </code></pre>
  <p>Assuming everything is set up and configured correctly, is this the correct URL for triggering the action in ExampleController.php?</p>
  <pre><code>http://my-craft-site/business-logic/example/example-route
  </code></pre>
  <p>If so, this is not working for me; it instead results in a 404/Template not found error. I'm not sure if I misunderstand how to determine the correct URL or if I set up something incorrectly.</p>
  <p>I am working with the example provided <a href="https://github.com/doublesecretagency/craft-businesslogic" rel="nofollow noreferrer">here</a> and I believe I have followed the <a href="https://doublesecretagency.github.io/craft-businesslogic/installation" rel="nofollow noreferrer">instructions</a> correctly. The instructions include a simple test of the module, and the test succeeds--I'm just not able to get the controller action to work as expected.</p>
  
Tags: <modules>
Title: What is the correct way to format a module controller action URL?
ThreadText: # What is the correct way to format a module controller action URL?
  
  (Asked by: username_0 on 2021-03-02)
  
  Consider the following Craft 3 example module structure:
  
  ```
  modules/
      businesslogic/
          controllers/ExampleController.php
          BusinessLogic.php
  
  ```
  
  ...and consider the following action in ExampleController.php:
  
  ```
  public function actionExampleRoute()
  {
      die('in example-route action');
  }
  
  ```
  
  Assuming everything is set up and configured correctly, is this the correct URL for triggering the action in ExampleController.php?
  
  ```
  http://my-craft-site/business-logic/example/example-route
  
  ```
  
  If so, this is not working for me; it instead results in a 404/Template not found error. I'm not sure if I misunderstand how to determine the correct URL or if I set up something incorrectly.
  
  I am working with the example provided [here](https://github.com/doublesecretagency/craft-businesslogic) and I believe I have followed the [instructions](https://doublesecretagency.github.io/craft-businesslogic/installation) correctly. The instructions include a simple test of the module, and the test succeeds--I'm just not able to get the controller action to work as expected.
  
  **Tags:** modules
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_0 on 2021-03-03. Score: 4 | Accepted answer
  
  The cause of the issue turned out to be an incorrect controllerNamespace reference in the [Business Logic Template](https://github.com/doublesecretagency/craft-businesslogic) example. If anyone else is using the example project to jumpstart a Craft module, be aware of the following:
  
  In that example, the ExampleController.php controller specifies this namespace...
  
  ```
  namespace modules\businesslogic\controllers;
  
  ```
  
  ...but BusinessLogic.php sets the controllerNameSpace like this, (note that it's missing **modules\**)...
  
  ```
  // Adjust controller namespace for console requests
  if (Craft::$app->getRequest()->getIsConsoleRequest()) {
      $this->controllerNamespace = 'businesslogic\\console\\controllers';
  }
  
  ```
  
  ...it worked for me after I changed it to match the ExampleController namespace, (note the addition of **modules\** as well as handling both console and web requests)...
  
  ```
  // Adjust controller namespace for console requests
  if (Craft::$app->getRequest()->getIsConsoleRequest()) {
      $this->controllerNamespace = 'modules\\businesslogic\\console\\controllers';
  } else {
      $this->controllerNamespace = 'modules\\businesslogic\\controllers';
  }
  
  ```
  
  **EDIT**
  
  To answer my own original question, the correct way to call the module action is:
  
  ```
  http://my-craft-site/actions/businesslogic/example/example-route
  
  ```
  
  Note that **/actions** precedes the *module/controller/action* portion of the URL, and that the controller and action are [kebab-cased](https://en.wiktionary.org/wiki/kebab_case). As @username_1 points out, the module is the module handle defined in *config/app.php*.
  
  
  ---
  
  ### Answer by username_1 on 2021-03-03. Score: 4
  
  It depends on the module handle you chose in *config/app.php* (the module handle is the key affected to your module in the `modules` array).
  
  If you want the URL to be `/business-logic/example/example-route`, the module key must be `business-logic`:
  
  ```php
  use modules\businesslogic\BusinessLogic;
  
  return [
      'modules' => [
          'business-logic' => BusinessLogic::class,
      ],
      'bootstrap' => [
          'business-logic',
      ]
  ];
  
  ```
  
  
  ---
  
  ### Answer by username_2 on 2021-03-03. Score: 2
  
  Whenever I'm using controllers for direct URL access (e.g. from JavaScript via an XHR or fetch request), I've accessed them using a query string rather than relying on rewritten URLs. So, like this:
  
  ```
  https://my-craft-site/index.php?p=actions/business-logic/example/example-route
  
  ```
  
  If the controller method is intended to be triggered from a form submit, you can just use the `actionInput` Twig function:
  
  ```
  <form method="post">
     {{ actionInput('business-logic/example/example-route') }}
  
     {# Some form input fields here... #}
  
      <button type="submit">
  </form>
  
  ```
  
  
  ---
  
  