Answers.Body: <p>Looks like you need to pass the csrf token through within your data as noted here <a href="https://craftcms.com/support/csrf-protection#updating-your-javascript" rel="nofollow noreferrer">https://craftcms.com/support/csrf-protection#updating-your-javascript</a></p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-27T15:19:46.087Z
Answers.Text: I tried this after seeing another post... but it didn't seem to work.
  also, it seemed odd that the plugin has csrf included but their ajax snippet supplied doesnt have this. So I assumed they must have included this in the plugin itself?
  https://github.com/craftcms/contact-form#ajax-form-submissions
Answers.UserDisplayName: ToddPadwick
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-27T15:12:05.113Z
Answers.LastActivityDate: 2017-10-27T15:12:05.113Z
Answers.UserDisplayName: hybrid_alex
Answers.Body: <p>Your form action attribute should not be empty (<code>$('input[name="action"]', form).attr('action')</code>) and your AJAX request should be sent using POST (<code>$.post</code>).</p>
  
  <pre><code>$.post('/', {
      dataType: 'json',
      action: $('input[name="action"]', form).attr('action'),
      data: $(this).serialize(),
      success: function(response) {
          if (response.success) {
              $('.request-ring-sizer .form-success').addClass("visible");
          } else {
  
              alert('An error occurred. Please try again.');
          }
      }
  });
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-30T14:07:45.057Z
Answers.Text: His action attribute is not empty and you don't need to use `$.post` instead of `$.ajax`, the way you described it sounds like `$.ajax` will not do the job but yours is just an alternative.
Answers.UserDisplayName: Robin Schambach
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-31T13:39:51.397Z
Answers.Text: To be more explicit, the default $.ajax method is GET (http://api.jquery.com/jquery.ajax/) and this plugin requires that data are send using POST (https://github.com/craftcms/contact-form/issues/102). If you want to use $.ajax instead of $.post you can, but you should specify the POST method parameter.
Answers.UserDisplayName: Romain P.
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-30T13:18:13.337Z
Answers.LastActivityDate: 2017-10-30T13:18:13.337Z
Answers.UserDisplayName: Romain P.
Answers.Body: <p>Turns out this was a mistake in the README docs. </p>
  
  <blockquote>
    <p>"The v1 README uses $.post, so this is only an issue when someone uses
    the v1 plugin and the v2 ajax instructions. I haven't tested it with
    v2, but it looks like the SendController requires POST too."</p>
  </blockquote>
  
  <p>The author of the plugin has now fixed this.</p>
  
  <p><a href="https://github.com/craftcms/contact-form/issues/102" rel="nofollow noreferrer">https://github.com/craftcms/contact-form/issues/102</a></p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-10-31T10:08:36.173Z
Answers.LastActivityDate: 2017-10-31T10:08:36.173Z
Answers.UserDisplayName: ToddPadwick
Body: <p>I am using the <a href="https://github.com/craftcms/contact-form/tree/v1" rel="nofollow noreferrer">Contact Form plugin</a> with AJAX. I have used the JS AJAX script supplied in the plugin but i get a 'Bad request: CSRF token could not be verified' error.
  I have seen many other posts on here regarding AJAX and CSRF but non seem to apply to the Contact Form plugin. </p>
  
  <p>Does anyone know how to get this to work?</p>
  
  <pre><code>&lt;form method="POST" action="" accept-charset="UTF-8" class="request-ring-sizer"&gt;
      {{ getCsrfInput() }}
      &lt;input type="hidden" name="action" value="contactForm/sendMessage"&gt;
  &lt;h2&gt;Order a free ring sizer&lt;/h2&gt;
  &lt;div class="inputGroup"&gt;
          &lt;h3 class="small"&gt;Contact details&lt;/h3&gt;
          &lt;div class="inputWrap{% if message is defined and message.hasErrors('fromName') %} error{% endif %}"&gt;
              &lt;input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-fromName" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}"&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;label for="ring-sizer-fromName"&gt;Your name&lt;/label&gt;
              &lt;span class="flash"&gt;{% if message is defined and message %}{{ message.getErrors('fromName') }}{% else %}Required{% endif %}&lt;/span&gt;
          &lt;/div&gt;
          &lt;div class="inputWrap{% if message is defined and message.hasErrors('fromEmail') %} error{% endif %}"&gt;
              &lt;input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="email" id="ring-sizer-fromEmail" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}"&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;label for="ring-sizer-fromEmail"&gt;Your email&lt;/label&gt;
              &lt;span class="flash"&gt;{% if message is defined and message %}{{ message.getErrors('fromEmail') }}{% else %}Required{% endif %}&lt;/span&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="inputGroup"&gt;
          &lt;h3 class="small"&gt;Your address&lt;/h3&gt;
          &lt;div class="inputWrap{% if message is defined and message.hasErrors('message[address1]') %} error{% endif %}"&gt;
              &lt;input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-message[address1]" name="message[address1]" value="{% if message is defined %}{{ message.message[address1] }}{% endif %}"&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;label for="ring-sizer-message[address1]"&gt;Address line 1&lt;/label&gt;
              &lt;span class="flash"&gt;{% if message is defined and message %}{{ message.getErrors('message[address1]') }}{% else %}Required{% endif %}&lt;/span&gt;
          &lt;/div&gt;
          &lt;div class="inputWrap"&gt;
              &lt;input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" type="text" id="ring-sizer-message[address2]" name="message[address2]" value="{% if message is defined %}{{ message.message[address2] }}{% endif %}"&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;label for="ring-sizer-message[address2]"&gt;Address line 2&lt;/label&gt;
          &lt;/div&gt;
          &lt;div class="inputWrap{% if message is defined and message.hasErrors('message[city]') %} error{% endif %}"&gt;
              &lt;input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-message[city]" name="message[city]" value="{% if message is defined %}{{ message.message[city] }}{% endif %}"&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;label for="ring-sizer-message[city]"&gt;Town or City&lt;/label&gt;
              &lt;span class="flash"&gt;{% if message is defined and message %}{{ message.getErrors('message[city]') }}{% else %}Required{% endif %}&lt;/span&gt;
          &lt;/div&gt;
          &lt;div class="inputWrap short{% if message is defined and message.hasErrors('message[zipCode]') %} error{% endif %}"&gt;
              &lt;input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-message[zipCode]" name="message[zipCode]" value="{% if message is defined %}{{ message.message[zipCode] }}{% endif %}"&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;label for="ring-sizer-message[zipCode]"&gt;Post code&lt;/label&gt;
              &lt;span class="flash"&gt;{% if message is defined and message %}{{ message.getErrors('message[zipCode]') }}{% else %}Required{% endif %}&lt;/span&gt;
          &lt;/div&gt;
          &lt;div class="inputWrap{% if message is defined and message.hasErrors('message[countryId]') %} error{% endif %}"&gt;
              &lt;select onkeydown="active(this);" onblur="validate(this)" class="address-country" name="message[countryId]" class="required"&gt;
                  &lt;option selected disabled&gt;Select a Country&lt;/option&gt;
                  {% for key, option in countries %}
                      &lt;option value="{{ key }}"&gt;{{ option }}&lt;/option&gt;
                  {% endfor %}
              &lt;/select&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;span class="flash"&gt;{% if message is defined and message %}{{ message.getErrors('message[countryId]') }}{% else %}Required{% endif %}&lt;/span&gt;
          &lt;/div&gt;
          &lt;div class="inputWrap"&gt;
              &lt;input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" type="text" id="ring-sizer-message[state]" name="message[state]" value="{% if message is defined %}{{ message.message[state] }}{% endif %}"&gt;
              &lt;span class="highlight"&gt;&lt;/span&gt;
              &lt;span class="bar"&gt;&lt;/span&gt;
              &lt;label for="ring-sizer-message[state]"&gt;State&lt;/label&gt;
          &lt;/div&gt;
          &lt;input name="preferredJewellery" type="text" style="display:none;"&gt;
          &lt;input type="hidden" id="ring-sizer-subject" name="subject" value="I would like to request a free ring sizer"&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;button type="submit" class="button button--primary button--primary--center page-fade"&gt;Submit&lt;/button&gt;
      &lt;div class="form-success"&gt;
          &lt;p class="center alert alert--success"&gt;Thank you. We will let you know when we've dispatched your free ring&amp;nbsp;sizer.&lt;/p&gt;
      &lt;/div&gt;&lt;!-- thanks --&gt;
  &lt;/form&gt;
  
  
  
  
  
  
  $(document).ready(function(){
  
      $('.request-ring-sizer').submit(function(ev) {
          console.log("ring sizer request submitted");
          // Prevent the form from actually submitting
          ev.preventDefault();
  
          // Send it to the server
          $.ajax('/', {
              dataType: 'json',
              data: $(this).serialize(),
              success: function(response) {
                  if (response.success) {
                      $('.request-ring-sizer .form-success').addClass("visible");
                  } else {
  
                      alert('An error occurred. Please try again.');
                  }
              }
          });
      });
  });
  </code></pre>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-10-27T09:30:45.423Z
Comments.Text: I you are using Craft 3, can you replace {{ getCsrfInput() }} with {{ csrfInput() }}? Alternatively, you could disable CSRF protection by adding 'enableCsrfProtection' => false in the craft/config/general.php config array (https://craftcms.com/support/csrf-protection).
Comments.UserDisplayName: Romain P.
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-10-27T09:49:29.640Z
Comments.Text: Craft 2. Didn't think Craft 3 was production ready yet.
  also, for security purposes surely it wouldn't be good to remove CSRF protection?
Comments.UserDisplayName: ToddPadwick
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-10-27T10:11:22.297Z
Comments.Text: You're right, Craft 3 is not yet production ready. And you're right also, remove CSRF protection is not recommended. But 'enableCsrfProtection' => false could help you to make the form working until you find a real solution.
Comments.UserDisplayName: Romain P.
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-10-27T11:00:53.560Z
Comments.Text: It seems that the form send data using GET instead of POST. Could you change $.ajax to $.post?
Comments.UserDisplayName: Romain P.
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-10-27T11:10:05.193Z
Comments.Text: That makes sense... I have just updated that. however I now get a new error:
  Uncaught TypeError: Cannot read property 'success' of undefined
Comments.UserDisplayName: ToddPadwick
Tags: <ajax><plugin-contactform><csrf>
Title: Contact Form plugin - using Ajax, CSRF 400 bad request
ThreadText: # Contact Form plugin - using Ajax, CSRF 400 bad request
  
  (Asked by: username_0 on 2017-10-27)
  
  I am using the [Contact Form plugin](https://github.com/craftcms/contact-form/tree/v1) with AJAX. I have used the JS AJAX script supplied in the plugin but i get a 'Bad request: CSRF token could not be verified' error.
  I have seen many other posts on here regarding AJAX and CSRF but non seem to apply to the Contact Form plugin.
  
  Does anyone know how to get this to work?
  
  ```
  <form method="POST" action="" accept-charset="UTF-8" class="request-ring-sizer">
      {{ getCsrfInput() }}
      <input type="hidden" name="action" value="contactForm/sendMessage">
  <h2>Order a free ring sizer</h2>
  <div class="inputGroup">
          <h3 class="small">Contact details</h3>
          <div class="inputWrap{% if message is defined and message.hasErrors('fromName') %} error{% endif %}">
              <input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-fromName" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}">
              <span class="highlight"></span>
              <span class="bar"></span>
              <label for="ring-sizer-fromName">Your name</label>
              <span class="flash">{% if message is defined and message %}{{ message.getErrors('fromName') }}{% else %}Required{% endif %}</span>
          </div>
          <div class="inputWrap{% if message is defined and message.hasErrors('fromEmail') %} error{% endif %}">
              <input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="email" id="ring-sizer-fromEmail" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}">
              <span class="highlight"></span>
              <span class="bar"></span>
              <label for="ring-sizer-fromEmail">Your email</label>
              <span class="flash">{% if message is defined and message %}{{ message.getErrors('fromEmail') }}{% else %}Required{% endif %}</span>
          </div>
      </div>
      <div class="inputGroup">
          <h3 class="small">Your address</h3>
          <div class="inputWrap{% if message is defined and message.hasErrors('message[address1]') %} error{% endif %}">
              <input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-message[address1]" name="message[address1]" value="{% if message is defined %}{{ message.message[address1] }}{% endif %}">
              <span class="highlight"></span>
              <span class="bar"></span>
              <label for="ring-sizer-message[address1]">Address line 1</label>
              <span class="flash">{% if message is defined and message %}{{ message.getErrors('message[address1]') }}{% else %}Required{% endif %}</span>
          </div>
          <div class="inputWrap">
              <input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" type="text" id="ring-sizer-message[address2]" name="message[address2]" value="{% if message is defined %}{{ message.message[address2] }}{% endif %}">
              <span class="highlight"></span>
              <span class="bar"></span>
              <label for="ring-sizer-message[address2]">Address line 2</label>
          </div>
          <div class="inputWrap{% if message is defined and message.hasErrors('message[city]') %} error{% endif %}">
              <input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-message[city]" name="message[city]" value="{% if message is defined %}{{ message.message[city] }}{% endif %}">
              <span class="highlight"></span>
              <span class="bar"></span>
              <label for="ring-sizer-message[city]">Town or City</label>
              <span class="flash">{% if message is defined and message %}{{ message.getErrors('message[city]') }}{% else %}Required{% endif %}</span>
          </div>
          <div class="inputWrap short{% if message is defined and message.hasErrors('message[zipCode]') %} error{% endif %}">
              <input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" class="required" type="text" id="ring-sizer-message[zipCode]" name="message[zipCode]" value="{% if message is defined %}{{ message.message[zipCode] }}{% endif %}">
              <span class="highlight"></span>
              <span class="bar"></span>
              <label for="ring-sizer-message[zipCode]">Post code</label>
              <span class="flash">{% if message is defined and message %}{{ message.getErrors('message[zipCode]') }}{% else %}Required{% endif %}</span>
          </div>
          <div class="inputWrap{% if message is defined and message.hasErrors('message[countryId]') %} error{% endif %}">
              <select onkeydown="active(this);" onblur="validate(this)" class="address-country" name="message[countryId]" class="required">
                  <option selected disabled>Select a Country</option>
                  {% for key, option in countries %}
                      <option value="{{ key }}">{{ option }}</option>
                  {% endfor %}
              </select>
              <span class="highlight"></span>
              <span class="bar"></span>
              <span class="flash">{% if message is defined and message %}{{ message.getErrors('message[countryId]') }}{% else %}Required{% endif %}</span>
          </div>
          <div class="inputWrap">
              <input onkeydown="active(this);" onblur="active(this); validate(this)" onfocus="active(this)" type="text" id="ring-sizer-message[state]" name="message[state]" value="{% if message is defined %}{{ message.message[state] }}{% endif %}">
              <span class="highlight"></span>
              <span class="bar"></span>
              <label for="ring-sizer-message[state]">State</label>
          </div>
          <input name="preferredJewellery" type="text" style="display:none;">
          <input type="hidden" id="ring-sizer-subject" name="subject" value="I would like to request a free ring sizer">
          </div>
      </div>
      <button type="submit" class="button button--primary button--primary--center page-fade">Submit</button>
      <div class="form-success">
          <p class="center alert alert--success">Thank you. We will let you know when we've dispatched your free ring&nbsp;sizer.</p>
      </div><!-- thanks -->
  </form>
  
  $(document).ready(function(){
  
      $('.request-ring-sizer').submit(function(ev) {
          console.log("ring sizer request submitted");
          // Prevent the form from actually submitting
          ev.preventDefault();
  
          // Send it to the server
          $.ajax('/', {
              dataType: 'json',
              data: $(this).serialize(),
              success: function(response) {
                  if (response.success) {
                      $('.request-ring-sizer .form-success').addClass("visible");
                  } else {
  
                      alert('An error occurred. Please try again.');
                  }
              }
          });
      });
  });
  
  ```
  
  **Tags:** ajax, plugin-contactform, csrf
  
  > **Comments:**
  > **username_1**: I you are using Craft 3, can you replace {{ getCsrfInput() }} with {{ csrfInput() }}? Alternatively, you could disable CSRF protection by adding 'enableCsrfProtection' => false in the craft/config/general.php config array (https://craftcms.com/support/csrf-protection).  
  > **username_0**: Craft 2. Didn't think Craft 3 was production ready yet. also, for security purposes surely it wouldn't be good to remove CSRF protection?  
  > **username_1**: You're right, Craft 3 is not yet production ready. And you're right also, remove CSRF protection is not recommended. But 'enableCsrfProtection' => false could help you to make the form working until you find a real solution.  
  > **username_1**: It seems that the form send data using GET instead of POST. Could you change $.ajax to $.post?  
  > **username_0**: That makes sense... I have just updated that. however I now get a new error: Uncaught TypeError: Cannot read property 'success' of undefined  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_2 on 2017-10-27. Score: 1
  
  Looks like you need to pass the csrf token through within your data as noted here <https://craftcms.com/support/csrf-protection#updating-your-javascript>
  
  > **Comments:**
  > **username_0**: I tried this after seeing another post... but it didn't seem to work. also, it seemed odd that the plugin has csrf included but their ajax snippet supplied doesnt have this. So I assumed they must have included this in the plugin itself? https://github.com/craftcms/contact-form#ajax-form-submissions  
  
  ---
  
  ### Answer by username_1 on 2017-10-30. Score: 0
  
  Your form action attribute should not be empty (`$('input[name="action"]', form).attr('action')`) and your AJAX request should be sent using POST (`$.post`).
  
  ```
  $.post('/', {
      dataType: 'json',
      action: $('input[name="action"]', form).attr('action'),
      data: $(this).serialize(),
      success: function(response) {
          if (response.success) {
              $('.request-ring-sizer .form-success').addClass("visible");
          } else {
  
              alert('An error occurred. Please try again.');
          }
      }
  });
  
  ```
  
  > **Comments:**
  > **username_3**: His action attribute is not empty and you don't need to use `$.post` instead of `$.ajax`, the way you described it sounds like `$.ajax` will not do the job but yours is just an alternative.  
  > **username_1**: To be more explicit, the default $.ajax method is GET (http://api.jquery.com/jquery.ajax/) and this plugin requires that data are send using POST (https://github.com/craftcms/contact-form/issues/102). If you want to use $.ajax instead of $.post you can, but you should specify the POST method parameter.  
  
  ---
  
  ### Answer by username_0 on 2017-10-31. Score: 0
  
  Turns out this was a mistake in the README docs.
  
  > "The v1 README uses $.post, so this is only an issue when someone uses
  > the v1 plugin and the v2 ajax instructions. I haven't tested it with
  > v2, but it looks like the SendController requires POST too."
  
  The author of the plugin has now fixed this.
  
  <https://github.com/craftcms/contact-form/issues/102>
  
  
  ---
  
  