Answers.Body: <p>The problem here was I hadn't included the <code>Accept</code> header</p>
  
  <pre class="lang-js prettyprint-override"><code>xhr.setRequestHeader("Accept", "application/json");
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-03-07T08:47:41.683Z
Answers.LastActivityDate: 2020-03-07T08:47:41.683Z
Answers.UserDisplayName: Timmy O'Mahony
Answers.Body: <p>In your newsletter form, you should have:</p>
  
  <pre><code>&lt;input type="hidden" name="action" value="mailchimp-subscribe/audience/subscribe"&gt;
  &lt;input type="hidden" name="language" value="{{ craft.app.locale.id }}"&gt;
  </code></pre>
  
  <p>Then, you should POST to <code>'/' + userLocale</code> (where <code>userLocale = $('[name="language"]').val()</code>).</p>
  
  <p>I am using jQuery, and this is working fine:</p>
  
  <pre><code>$.post({
      url: '/' + userLocale,
      dataType: 'json',
      data: $('#form').serialize(),
      success: function(response) {
          console.log(response);
      },
      error: function(response) {
          console.log(response);
      }
  });
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-03-02T16:39:04.903Z
Answers.Text: Thanks but I'm trying to do it without jQuery as vanilla JS. Also I don't have any localization. I've tried posting to the root URL with the included hidden inputs but it still throws errors
Answers.UserDisplayName: Timmy O'Mahony
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-03-02T16:42:26.513Z
Answers.Text: To the root URL, you mean `'/'`? Maybe you can also add this to the `<head>` tag: `<base href="{{ alias('@web/') }}">`.
Answers.UserDisplayName: Romain P.
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-03-02T15:38:49.350Z
Answers.LastActivityDate: 2020-03-02T15:38:49.350Z
Answers.UserDisplayName: Romain P.
Body: <p>I want to use Ajax to POST to a plugin endpoint and get a JSON response. The plugin I'm using is for Mailchimp newsletter subscriptions and should allow for JSON responses:</p>
  <p><a href="https://github.com/aelvan/mailchimp-subscribe-craft" rel="nofollow noreferrer">https://github.com/aelvan/mailchimp-subscribe-craft</a></p>
  <p>I have my form:</p>
  <pre><code>&lt;form action=&quot;&quot; method=&quot;post&quot; novalidate&gt;
    {{ csrfInput() }}
    &lt;input id=&quot;email&quot; name=&quot;email&quot; type=&quot;email&quot; &gt;
    &lt;input type=&quot;submit&quot; value=&quot;Subscribe&quot;&gt;
  </code></pre>
  <p>and my Javascript:</p>
  <pre><code>let json = this.toJSONString(this.form);
  let xhr = new XMLHttpRequest();
  xhr.onload = () =&gt; {
    if (xhr.status &gt;= 200 &amp;&amp; xhr.status &lt; 300) {
      // ...
    } else {
       // ...
    }
  };
  xhr.open(&quot;POST&quot;, &quot;actions/mailchimp-subscribe/audience/subscribe&quot;, true);
  xhr.setRequestHeader(&quot;Content-Type&quot;, &quot;application/json; charset=UTF-8&quot;);
  xhr.send(json);
  </code></pre>
  <p>This hits the endpoint, but I get a 404 response:</p>
  <blockquote>
  <p>HTTP 404 – Not Found – yii\web\NotFoundHttpException</p>
  <p>Template not found: actions/mailchimp-subscribe/audience/subscribe</p>
  </blockquote>
  <p>As I understand it, I'm correctly posting to the relevent plugin controller action by using the URL <code>actions/mailchimp-subscribe/audience/subscribe</code>. Furthermore, if I do a GET to that URL I get a <code>400</code> response which would lead me to believe the routing is correct.</p>
  <p>The error therefore seems to be in the Craft controller/routing handler. It's not detecting that I've send a JSON string and that I want a JSON response (and not a template/HTML response).</p>
  <p>What's going on here?</p>
  
Tags: <craft3>
Title: Posting to plugin's action controller using Ajax + JSON
ThreadText: # Posting to plugin's action controller using Ajax + JSON
  
  (Asked by: username_0 on 2020-03-02)
  
  I want to use Ajax to POST to a plugin endpoint and get a JSON response. The plugin I'm using is for Mailchimp newsletter subscriptions and should allow for JSON responses:
  
  <https://github.com/aelvan/mailchimp-subscribe-craft>
  
  I have my form:
  
  ```
  <form action="" method="post" novalidate>
    {{ csrfInput() }}
    <input id="email" name="email" type="email" >
    <input type="submit" value="Subscribe">
  
  ```
  
  and my Javascript:
  
  ```
  let json = this.toJSONString(this.form);
  let xhr = new XMLHttpRequest();
  xhr.onload = () => {
    if (xhr.status >= 200 && xhr.status < 300) {
      // ...
    } else {
       // ...
    }
  };
  xhr.open("POST", "actions/mailchimp-subscribe/audience/subscribe", true);
  xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
  xhr.send(json);
  
  ```
  
  This hits the endpoint, but I get a 404 response:
  
  > HTTP 404 – Not Found – yii\web\NotFoundHttpException
  >
  > Template not found: actions/mailchimp-subscribe/audience/subscribe
  
  As I understand it, I'm correctly posting to the relevent plugin controller action by using the URL `actions/mailchimp-subscribe/audience/subscribe`. Furthermore, if I do a GET to that URL I get a `400` response which would lead me to believe the routing is correct.
  
  The error therefore seems to be in the Craft controller/routing handler. It's not detecting that I've send a JSON string and that I want a JSON response (and not a template/HTML response).
  
  What's going on here?
  
  **Tags:** craft3
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_0 on 2020-03-07. Score: 1 | Accepted answer
  
  The problem here was I hadn't included the `Accept` header
  
  ```js
  xhr.setRequestHeader("Accept", "application/json");
  
  ```
  
  
  ---
  
  ### Answer by username_1 on 2020-03-02. Score: 1
  
  In your newsletter form, you should have:
  
  ```
  <input type="hidden" name="action" value="mailchimp-subscribe/audience/subscribe">
  <input type="hidden" name="language" value="{{ craft.app.locale.id }}">
  
  ```
  
  Then, you should POST to `'/' + userLocale` (where `userLocale = $('[name="language"]').val()`).
  
  I am using jQuery, and this is working fine:
  
  ```
  $.post({
      url: '/' + userLocale,
      dataType: 'json',
      data: $('#form').serialize(),
      success: function(response) {
          console.log(response);
      },
      error: function(response) {
          console.log(response);
      }
  });
  
  ```
  
  > **Comments:**
  > **username_0**: Thanks but I'm trying to do it without jQuery as vanilla JS. Also I don't have any localization. I've tried posting to the root URL with the included hidden inputs but it still throws errors  
  > **username_1**: To the root URL, you mean `'/'`? Maybe you can also add this to the `<head>` tag: `<base href="{{ alias('@web/') }}">`.  
  
  ---
  
  