This is only a problem for me in my newest dot net core 2 web app, it works in previous dot net apps with no issue.
I have a custom javascript file with paths to various servers that my site is hosted on(mainly dev, test, live).
My ajax call looks like the following:
var gameid = '#Html.Raw(Model.Id)';
$.ajax({
type: 'GET',
url: url() + "UserGames/HasGame?id=" +gameid,
cache: false,
success: function (data) {
console.log(data);
},
error: function (req, status, err) {
console.log('Something went wrong', status, err);
}
});
The url() in question is simply looking at my local server while testing(*please note, this port has been edited, it is correct):
function url() {
return "https://localhost:4432/";
}
The error is not firing as it isnt even reaching the controller function being used.
I'm absolutely bemused as to why this isnt working, i could understand if i was getting some sort of error back, but i have used ajax calls in all of my apps and not had this problem at all until using core 2.
Has anything changed that may have affected the way you use ajax calls?
Method that is trying to fire, but i mentioned, it isnt hitting the controller(NOTE: the method does have code in it, it just isnt hitting the controller in the first place)
[HttpGet]
[ValidateAntiForgeryToken]
public async Task<IActionResult> HasGame(int id)
{
//stuff in here
}
You are getting a 400 (Bad Request) response because the framework expects the RequestVerificationToken as part of the request.The framework uses this to prevent possible CSRF attacks. If your request does not have this information, the framework will return the 400 bad request. Your current code is not sending it.
You can fix it by explicitly send that RequestVerificationToken
The form tag helper automatically creates a hidden input with name atttribute value __RequestVerificationToken and stores the token as the value of the hidden input.
var token = $("[name='__RequestVerificationToken']").val();
var gameid = '#Html.Raw(Model.Id)';
$.ajax({
type: 'GET',
url: url() + "UserGames/HasGame?id=" +gameid,
headers:{ "RequestVerificationToken": token },
success: function (data) {
console.log(data);
},
error: function (req, status, err) {
console.log('Something went wrong', status, err);
}
});
In the above example, we are using some jQuery code to get the input element with name __RequestVerificationToken and reading the value of it. A more robust approach would be injecting the IAntiforgery implementation to the view and using the GetAndStoreTokens method.
We will be injecting IHttpContextAccessor to the view. So make sure it is wired up with DI properly. Add this line to your Startup classes' ConfigureServices method.
services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();
Now in your view, you can inject IHttpContextAccessor and IAntiforgery and then call the GetAndStoreTokens to get the token. Here i wrapped that into a helper function.
#inject Microsoft.AspNetCore.Http.IHttpContextAccessor HttpContext
#inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
#functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(HttpContext.HttpContext).RequestToken;
}
}
Now later in my js, i can call this method inside my javascript code instead of using jQuery to get the input value.
var token = "#GetAntiXsrfRequestToken()";
var gameid = '#Html.Raw(Model.Id)';
$.ajax({
type: 'GET',
url: url() + "UserGames/HasGame?id=" +gameid,
headers:{ "RequestVerificationToken": token },
success: function (data) {
console.log(data);
},
error: function (req, status, err) {
console.log('Something went wrong', status, err);
}
});
Or Simply remove [ValidateAntiForgeryToken] attribute decoration from the action method, which excludes this check.
I recommend you to take advantage of the[ValidateAntiForgeryToken] method. Send the token as part of your request(first approach)
If anyone else comes across this issue, i managed to fix it by doing the following to both the call and the controller:
type: 'GET',
url: '#Url.Action("HasGame", "UserGames")',
data: {id : gameid},
And the controller in core 2 does not seem to like you declaring [HttpGet] at all, so i removed that also.
Thanks for all the help provided.
I have the following AJAX request:
$.ajax({
url: "/api/newrentals",
dataType: "json",
type: "PUT",
data: columnDate
}).done(function() {
toastr.success("Rentals succesfully recorded.");
}).fail(function() {
toastr.error("Something unexpected happened.");
});
And here's my CONTROLLER:
using System.Web.Http; //I used the correct reference
public class NewRentalsController : ApiController {
[HttpPut]
public void updateRentalReturnDate(string columnDate){
var date = columnDate;
}
}
When I hit some button, the ajax request is executed but it does not reach the controller. I get the following error :
"message": "The requested resource does not support http method 'PUT'."
I have read many answers but nothing helped me. For instance, I made sure that the paramater name in ajax and in the controller should be same. I also put the [HttpPut] annotation in the controller method. What exactly am I missing here?
I'm calling an ASP.NET MVC 4 control method from Javascript (in a cshtml file) using $.ajax() as shown below
$.ajax({
url: '#Url.Action("MyAction", "MyController")',
type: 'GET',
data: { 'id': "123"},
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function (data) {
}
});
The controller action method is
public JsonResult MyAction(string id)
{
// Do stuff
return new JsonResult();
}
which is getting called ok but is causing a GET 500 (Internal Server Error).
I don't really care about the returned data I just want to call the controller method to update a model.
Can anyone let me know why I'm getting the 500 or an alternative way of doing this that would be great.
For security reasons you cannot use the GET method in ajax requests (See JSON Hijacking).
You just have to do it like this:
return Json(data, JsonRequestBehavior.AllowGet)
or better off, change the method to post
type: 'POST',
I am using the following syntax to make a call to controller method from ASP page.
$.ajax({
url: 'ControllerName/MethodName',
type: 'POST',
contentType: 'application/json;',
data: JSON.stringify({ param: param1}),
success: function () {
alert("Success!!!");
},
error: function () {
alert("Failed!!!");
}
});
I have two ASP pages (views), both having same controller. If I call above method from first page, controller method gets called successfully. But if call same method from second page I get alert message "Failed". Also I tried using GET type, tried with other controller methods and all. Nothing will be called from second view. can anyone help me what can be problem? I am new to MVC.
Since your ajax is expecting result of JSON data from your Controller method do you have return Json(data, JsonRequestBehavior.AllowGet)?
Try change content type to:
contentType: 'application/json; charset=utf-8'
or/and specify url using mvc helper like:
url: #Url.Action("action"),
Works in my example. Hope it will help.
I have an action method that is invoked with POST method over AJAX. Method looks like this:
[HttpPost]
public ActionResult Save(MyModel model)
{
/// do something and save
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
What happens is that after this method is call by the $.ajax, from unknown reason follow up GET request is made to same controller and same action. This call is not made anywhere and it's probably implemented either in browser or in ASP.NET MVC as Post/Redirect/Get pattern which I don't need in this case.
Is there a way to disable this programmatically because GET counterpart of Save method is not implemented and server returns 404 with HTML contents in it.
EDIT, this is the client-side AJAX script:
function saveDonkey(donkey) {
var jsonData = JSON.stringify(donkey);
$.ajax({
url: "/Donkey/Save",
data: jsonData,
contentType: "application/json",
dataType: "json",
type: "POST",
success: function () {
fetchPage(); /// This just issues GET request to another predefined method
}
});
}