Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Continually receiving 400 (Bad Request) on jquery ajax post to MVC controller

My ajax call looks like this

$.ajax({ //actually approve or reject the promotion
                url: url,
                type: "POST",
                data: '{'+data.PromotionId+','+data.UserId+','+data.ReasonText+'}',
                dataType: "json",
                //contentType: "application/json; charset=utf-8",
                success: function (data) {
                    if (indicator == 'A') {
                        alert('Promotion approved successfully!');
                    }
                    else {
                        alert('Promotion rejected successfully.');
                    }

                    var homelink = '<%: Url.Action("Index","Home") %>';
                    window.location.href = (homelink);


                    returndata = data;
                },
                error: function (xhRequest, ErrorText, thrownError) {
                    alert("Failed to process promotion correctly, please try again");
                    console.log('xhRequest: ' + xhRequest + "\n");
                    console.log('ErrorText: ' + ErrorText + "\n");
                    console.log('thrownError: ' + thrownError + "\n");
                }
            });

And my MVC controller looks like this:

 [HttpPost]
    public HttpResponseMessage ApprovePromotion(PromotionDecision decision)
    {
        if (ModelState.IsValid && decision != null)
        {
            bool status = PromotionBo.ApprovePromotion(decision);
            if (status == true)
                return new HttpResponseMessage(HttpStatusCode.OK);
        }
        return new HttpResponseMessage(HttpStatusCode.BadRequest);
    }

I had thought the syntax was correct on both of these however every time I make the ajax call I get a 400 response. What is it that I am doing wrong?

like image 555
Pseudonym Avatar asked Jan 11 '13 15:01

Pseudonym


2 Answers

You are sending a completely broken and invalid JSON string to the server. It's normal that the controller action rejects it. In addition to that you have put into comments the contentType parameter specifying that you want to send a JSON request.

So here's the correct way to do the request:

$.ajax({ //actually approve or reject the promotion
    url: url,
    type: "POST",
    data: JSON.stringify({ 
        // Those property names must match the property names of your PromotionDecision  view model
        promotionId: data.PromotionId, 
        userId: data.UserId, 
        reasonText: data.ReasonText
    }),
    contentType: "application/json; charset=utf-8",
    success: function (data) {
        if (indicator == 'A') {
            alert('Promotion approved successfully!');
        }
        else {
            alert('Promotion rejected successfully.');
        }

        var homelink = '<%: Url.Action("Index","Home") %>';
        window.location.href = (homelink);

        returndata = data;
    },
    error: function (xhRequest, ErrorText, thrownError) {
        alert("Failed to process promotion correctly, please try again");
        console.log('xhRequest: ' + xhRequest + "\n");
        console.log('ErrorText: ' + ErrorText + "\n");
        console.log('thrownError: ' + thrownError + "\n");
    }
});

Notice how I am using the JSON.stringify method that is natively built-into modern browsers to ensure that the JSON being sent to the server is correctly and all values are properly encoded. And if you need to support browsers from the stone age, you could include the json2.js script to your page which will define the JSON.stringify method.

Important remark: Absolutely never build JSON strings using string concatenations as in your code.

Alternatively if you don't want to send a JSON request you could send a standard application/x-www-form-urlencoded request:

$.ajax({ //actually approve or reject the promotion
    url: url,
    type: "POST",
    data: { 
        promotionId: data.PromotionId, 
        userId: data.UserId, 
        reasonText: data.ReasonText
    },
    success: function (data) {
        if (indicator == 'A') {
            alert('Promotion approved successfully!');
        }
        else {
            alert('Promotion rejected successfully.');
        }

        var homelink = '<%: Url.Action("Index","Home") %>';
        window.location.href = (homelink);

        returndata = data;
    },
    error: function (xhRequest, ErrorText, thrownError) {
        alert("Failed to process promotion correctly, please try again");
        console.log('xhRequest: ' + xhRequest + "\n");
        console.log('ErrorText: ' + ErrorText + "\n");
        console.log('thrownError: ' + thrownError + "\n");
    }
});

This should work the same way and the controller action should be able to properly bind the model.

Remark: I have noticed that you used the following line in your success callback: returndata = data;. This leads me to believe that you are somehow attempting to consume the result of an asynchronous AJAX request outside of the success callback which is not possible. I have no idea what you are doing with this returndata variable but I feel it is wrong.

like image 105
Darin Dimitrov Avatar answered Sep 23 '22 10:09

Darin Dimitrov


This error also occurs when using [ValidateAntiForgeryToken] attribute for MVC action method in combination with Ajax call.

Check this out, might help as well: https://stackoverflow.com/a/60952294/315528

like image 26
ticky Avatar answered Sep 22 '22 10:09

ticky