63

I am trying to send an Ajax POST request using Jquery but I am having 400 bad request error.

Here is my code:

$.ajax({
  type: 'POST',
  url: "http://localhost:8080/project/server/rest/subjects",
  data: {
    "subject:title":"Test Name",
    "subject:description":"Creating test subject to check POST method API",
    "sub:tags": ["facebook:work", "facebook:likes"],
    "sampleSize" : 10,
    "values": ["science", "machine-learning"]
  },
  error: function(e) {
    console.log(e);
  }
});

It Says: Can not build resource from request. What am I missing ?

Sachin Jain
  • 21,353
  • 33
  • 103
  • 168

6 Answers6

125

Finally, I got the mistake and the reason was I need to stringify the JSON data I was sending. I have to set the content type and datatype in XHR object. So the correct version is here:

$.ajax({
  type: 'POST',
  url: "http://localhost:8080/project/server/rest/subjects",
  data: JSON.stringify({
    "subject:title":"Test Name",
    "subject:description":"Creating test subject to check POST method API",
    "sub:tags": ["facebook:work", "facebook:likes"],
    "sampleSize" : 10,
    "values": ["science", "machine-learning"]
  }),
  error: function(e) {
    console.log(e);
  },
  dataType: "json",
  contentType: "application/json"
});

May be it will help someone else.

Sachin Jain
  • 21,353
  • 33
  • 103
  • 168
  • 5
    Could've saved myself an hour of frustrated debugging if I'd found this to begin with. Thanks ;) – bugsduggan Mar 22 '14 at 18:14
  • 7
    As once said by Thomas Edison, "You haven't failed, you have learnt N ways that won't work" in that hour So be glad that you didn't find it earlier and tried to solve the problem yourself. – Sachin Jain Mar 23 '14 at 01:52
  • 1
    This helped me. Why is this step necessary? – JasonTS Mar 17 '15 at 03:11
  • 1
    I had [exactly the same problem](http://stackoverflow.com/questions/35287054/why-does-this-ajax-post-fails-with-elasticsearch) and this is the only place where `JSON.stringify()` is mentioned. Why is it needed? – WoJ Feb 09 '16 at 10:22
  • 4
    4 years later your answer just helped someone who was tearing their hair out for 2 hours. Thanks so much. – user2490003 Feb 09 '17 at 09:36
  • Thanks, solved my issue. Though, I'm still lost on why we need to convert the data object into a string. From the jQuery spec, the method should be able to take in a JS PlainObject and automatically convert it into a string. – Jonathan Feb 15 '17 at 22:59
  • If you are using jquery than you can directly use jquery alternative of JSON.stringify : $.param(data) – CodingEra Jul 29 '20 at 08:11
10

Yes. You need to stringify the JSON data orlse 400 bad request error occurs as it cannot identify the data.

400 Bad Request

Bad Request. Your browser sent a request that this server could not understand.

Plus you need to add content type and datatype as well. If not you will encounter 415 error which says Unsupported Media Type.

415 Unsupported Media Type

Try this.

var newData =   {
                  "subject:title":"Test Name",
                  "subject:description":"Creating test subject to check POST method API",
                  "sub:tags": ["facebook:work", "facebook:likes"],
                  "sampleSize" : 10,
                  "values": ["science", "machine-learning"]
                  };

var dataJson = JSON.stringify(newData);

$.ajax({
  type: 'POST',
  url: "http://localhost:8080/project/server/rest/subjects",
  data: dataJson,
  error: function(e) {
    console.log(e);
  },
  dataType: "json",
  contentType: "application/json"
});

With this way you can modify the data you need with ease. It wont confuse you as it is defined outside the ajax block.

Du-Lacoste
  • 11,530
  • 2
  • 71
  • 51
10

In case anyone else runs into this. I have a web site that was working fine on the desktop browser but I was getting 400 errors with Android devices.

It turned out to be the anti forgery token.

$.ajax({
        url: "/Cart/AddProduct/",
        data: {
            __RequestVerificationToken: $("[name='__RequestVerificationToken']").val(),
            productId: $(this).data("productcode")
        },

The problem was that the .Net controller wasn't set up correctly.

I needed to add the attributes to the controller:

    [AllowAnonymous]
    [IgnoreAntiforgeryToken]
    [DisableCors]
    [HttpPost]
    public async Task<JsonResult> AddProduct(int productId)
    {

The code needs review but for now at least I know what was causing it. 400 error not helpful at all.

Norbert Norbertson
  • 2,102
  • 1
  • 16
  • 28
2

The question is a bit old... but just in case somebody faces the error 400, it may also come from the need to post csrfToken as a parameter to the post request.

You have to get name and value from craft in your template :

<script type="text/javascript">
    window.csrfTokenName = "{{ craft.config.csrfTokenName|e('js') }}";
    window.csrfTokenValue = "{{ craft.request.csrfToken|e('js') }}";
</script>

and pass them in your request

data: window.csrfTokenName+"="+window.csrfTokenValue
1

I'm hoping this may be of use to those encountering 400 errors while using AJAX in Wordpress going forward. Even though this question is many years old, the solutions provided have all been programmatic, and I'm sure many have stepped through their code to repeatedly find it's correct, yet continue to find it is not working.

I found dozens of results asking how to resolve "WP AJAX request returning 400 Bad Request" or "WP AJAX request returning 0" and nothing today worked.

Googling "How do I fix 400 bad request on Wordpress?" finally resulted in the answer appearing from https://wp-umbrella.com/troubleshooting/400-bad-request-error-on-wordpress/

Clear your Web Browser Cache and Cookies

You may be surprised, but most 400 errors in WordPress can be fixed by clearing your browser's cache and cookies. Browser caches temporarily store images, scripts, and other parts of websites you visit to speed up your browsing experience.

Clearing both my cache and cookies saw the 400 Bad Request code disappear and results return AJAX results as expected.

Patrick Jackson
  • 336
  • 1
  • 4
0

You need to build query from "data" object using the following function

function buildQuery(obj) {
        var Result= '';
        if(typeof(obj)== 'object') {
            jQuery.each(obj, function(key, value) {
                Result+= (Result) ? '&' : '';
                if(typeof(value)== 'object' && value.length) {
                    for(var i=0; i<value.length; i++) {
                        Result+= [key+'[]', encodeURIComponent(value[i])].join('=');
                    }
                } else {
                    Result+= [key, encodeURIComponent(value)].join('=');
                }
            });
        }
        return Result;
    }

and then proceed with

var data= {
"subject:title":"Test Name",
"subject:description":"Creating test subject to check POST method API",
"sub:tags": ["facebook:work, facebook:likes"],
"sampleSize" : 10,
"values": ["science", "machine-learning"]
}

$.ajax({
  type: 'POST',
  url: "http://localhost:8080/project/server/rest/subjects",
  data: buildQuery(data),
  error: function(e) {
    console.log(e);
  }
});
  • you don't "have" to, jQuery will attempt to do it for you. Though, if you do build it yourself, you can guarantee it's in the format you want it to be in. – Kevin B Apr 15 '13 at 15:16
  • I don't think I need to build Object using this way. Jquery does this heavy lifting for me. Moreover, whenever data is sent via POST method it is always encoded so we need not use encodeURIComponent over the data to be sent. – Sachin Jain Apr 15 '13 at 17:01