Reputation: 111
I am working on ASP.NET Zero which is built on ASP.NET Core. I was getting a bad request error when I used KendoUI Upload control on one of my pages. After lot of research and investigation, I realized the HTTP POST Ajax request is failing with 400 bad request error. My code samples below have some commented line for other scenarios I test. None of the existing posts in stack over flow solved my issue. I Below is my ajax call:
$.ajax({
url: "/test/TestCall",
type: 'Post',
/* data: JSON.stringify({ "Param1": "test" }),
dataType:"json",
processData: false, */// tell jQuery not to process the data
contentType: "application/json", // tell jQuery not to set contentType
success: function (result) {
var res = result;
},
error: function (jqXHR) {
var z = 3;
},
complete: function (jqXHR, status) {
var x = 10;
}
});
My Controller code is: I also tried without extending from MyTestProjectControllerBase and just using the Controller base class. It did not work.
public class TestController : MyTestProjectControllerBase
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult TestCall()
{
//return Content("Name is:" );
return new ContentResult() { Content = "test" };
}
}
What am I missing? I tried using postman and I see this additional information 'Request cannot be fulfilled due to bad syntax'
could not figure it out after spending good 8 hours on this issue. Not sure if the issue is with Asp.net core or asp.net zero. Any pointers would be greatly appreciated.
Update after checking the comments by shyju: Startup.cs file has the following code that enables AntiForgeryTokenAttribute
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
Updates to the ajax call and view based on answer by shyju:
$("#backBtn").on("click", function (e) {
var t = $("input[name='__RequestVerificationToken']").val();
$.ajax({
url: "/test/TestCall",
type: 'Post',
/* data: JSON.stringify({ "Param1": "test" }),
dataType:"json",
processData: false, */
contentType: "application/json",
headers: {
"RequestVerificationToken": t
},
success: function (result) {
var res = result;
},
error: function (jqXHR) {
var z = 3;
},
complete: function (jqXHR, status) {
var x = 10;
}
});
});
My view looks like this now:removed rest of the html
<div id="container">
@Html.AntiForgeryToken()
<div class="k-edit-field label">Vendor Name</div>
</div
Upvotes: 10
Views: 18524
Reputation: 1244
In Net Core RazorPages, you will have to pass AntiForgeryToken with JQuery Ajax Post request. if you have a Form tag with Method=Post then you do not have to worry about sending it.
$.ajax({
type:"post",
url:"?Handler=Update",
dataType:"json",
beforeSend: function(xhr){
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
success: function(result){
// do something
}
});
Then in your Razor Page
@using Microsoft.AspNetCore.Antiforgery
@inject IAntiforgery antiforgery
@{
var token = antiforgery.GetAndStoreTokens(HttpContext).RequestToken;
}
Be sure to add
@Html.AntiForgeryToken()
Then in your StartUp.cs inside ConfigureServices method, add
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
Upvotes: 3
Reputation: 729
In Core -- make sure your <form>
tag includes method="post"
.
The method is required to invoke the form tag helper which automatically adds the antiforgery token to the form. (I accidentally left off the method and didn't notice because I was ajax-posting it.)
Upvotes: 3
Reputation: 30056
Try to specify the header with X-XSRF-TOKEN
.
For ABP Intercept XMLHttpRequest.
Since all libraries use JavaScript's native AJAX object, XMLHttpRequest, you can define a simple interceptor to add the token to the header:
(function (send) {
XMLHttpRequest.prototype.send = function (data) {
this.setRequestHeader(abp.security.antiForgery.tokenHeaderName, abp.security.antiForgery.getToken());
return send.call(this, data);
};
})(XMLHttpRequest.prototype.send);
For abp.security.antiForgery.tokenHeaderName
, its default value is X-XSRF-TOKEN
Upvotes: 0
Reputation: 218892
Looks like you have AutoValidateAntiforgeryTokenAttribute
filter applied globally. That means when an HTTP Post action method is called(normal or ajax), the framework will check the submitted request data and if it does not find a valid anti forgery token(RequestVerificationToken
header), it will be considered a bad request and a 400 response will be sent back.
To fix this problem, you can explicitly read the value of __RequestVerificationToken
hidden input (generated by the form tag helper) and send that in your ajax request headers.
var t = $("input[name='__RequestVerificationToken']").val();
$.ajax({
url: "/test/TestCall",
type: 'Post',
headers:
{
"RequestVerificationToken": t
},
success: function (result) {
alert("Success");
var res = result;
},
error: function (jqXHR) {
var z = 3;
},
complete: function (jqXHR, status) {
var x = 10;
}
});
You can make the code more robust by injecting the IAntiforgery
implementation to the view/page and using the GetAndStoreTokens
method.
Add this to your view
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}
and call this GetAntiXsrfRequestToken function to get the value in your javascript ( which is inside the view file)
headers:
{
"RequestVerificationToken": '@GetAntiXsrfRequestToken()'
},
Upvotes: 17