Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
516 views
in Technique[技术] by (71.8m points)

javascript - The required anti-forgery form field “__RequestVerificationToken” is not present in ajax call

I have the following method in controller

[HttpPost]
[Authorize(Roles ="Klient")]
[ValidateAntiForgeryToken]
public ActionResult GetAvaiableHouses(DateTime startDate, DateTime endDate)
{
    Session.Remove("Reservation");
    IEnumerable <SelectListItem> avaiableHouses = repository.GetAllNamesAvaiableHouses(repository.GetAvaiableHousesInTerm(startDate, endDate));

    List<string> houses = new List<string>();
    avaiableHouses.ToList().ForEach(item => houses.Add(item.Value));

    if(avaiableHouses.ToList().Count == 0)
    {
        return new EmptyResult();
    }

    Session["Reservation"] = new NewReservation()
    {
        StartDate = startDate,
        EndDate = endDate,
        AvaiableHouses = avaiableHouses
    };

    return PartialView("~/Views/Shared/_AvaiableHousesPartial.cshtml", houses);
}

This method is called by using ajax script in View.cshtml

$(function () {
    $("#btnCheckAvaiableHouses").click(function () {

        $.ajax({
            type: "POST",
            url: "/ClientReservations/GetAvaiableHouses",
            data: '{startDate: "' + $("#startdate").val() + '",endDate:"' + $("#enddate").val() + '",__RequestVerificationToken:"' + $('input[name=__RequestVerificationToken]').val() +'"  }',
            contentType: "application/json; charset=utf-8",
            dataType: "text",
            success: function (response) {
                $('#avaiableHouses').html(response)
                if (!$('#avaiableHouses').is(':empty')) {
                    document.getElementById("btnConfirmTerm").style.visibility = 'visible';
                }
                else {
                    $('#avaiableHouses').html('Brak dost?pnych domków w podanym terminie')
                }
            },
            failure: function (response) {
                alert(response.responseText);
            },
            error: function (response) {
                alert(response.responseText);
            }
        });
    });
});

This is the section of buttons with this one which call this script

<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="button" id="btnCheckAvaiableHouses" value="Sprawd? dost?pno?? domków" class="btn btn-default" /> 
        <input type="button" id="btnConfirmTerm" value="Potwierd? termin" onclick="location.href='@Url.Action("Create", "ClientReservations")'"  class="btn btn-default" style="visibility:hidden" />
    </div>
</div>

I have added the additional parameter

'",__RequestVerificationToken:"' + $('input[name=__RequestVerificationToken]').val() 

into ajax script but during execution I still receive the error

,__RequestVerificationToken is not present.

What could be the reason?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If your stringifying the data and using contentType: 'application/json, then add the token to the ajax headers, for example

var headers = { __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() };

$.ajax({
    headers: headers,
    data: ... // remove the token from your existing implementation
    ....
});

and then you need to create a custom FilterAttribute to read the value from the Headers

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        var httpContext = filterContext.HttpContext;
        var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
        AntiForgery.Validate(cookie != null ? cookie.Value : null, httpContext.Request.Headers["__RequestVerificationToken"]);
    }
}

and in your controller method, replace [ValidateAntiForgeryToken] with [ValidateHeaderAntiForgeryToken]

However, it is not necessary to stringify the data, and you can use

var data = {
    startDate: $("#startdate").val(),
    endDate: $("#enddate").val(),
    __RequestVerificationToken: $('input[name=__RequestVerificationToken]').val()
};

$.ajax({
    data: data,
    ....
});

and remove the contentType option so it uses the default 'application/x-www-form-urlencoded; charset=UTF-8'

You have not shown your form, assuming it contains @Html.AntiForgeryToken() and @Html.TextBoxFor(m => m.startDate) and @Html.TextBoxFor(m => m.endDate) to that you generate form controls with name="startDate" and name="endDate", then you can simply use

var data = $('form').serialize();

$.ajax({
    data: data,
    ....
});

to serialize all your form controls including the token


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...