Why is this basic ajax call giving me a 400 and not firing to the controller?

好久不见. 提交于 2019-12-20 06:04:10

问题


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
}

回答1:


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)




回答2:


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.



来源:https://stackoverflow.com/questions/51139967/why-is-this-basic-ajax-call-giving-me-a-400-and-not-firing-to-the-controller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!