Подтвердить что ты не робот

Проводка AJAX ValidateAntiForgeryToken без формы для метода действия MVC

Я смотрел примеры того, как это сделать на SO, и насколько я могу судить, я пробовал все примеры, которые я могу найти без успеха до сих пор. Я попытался изменить некоторые из реализаций моего сценария, но пока это не удалось.

У меня есть это на моей странице в _layout.cshtml, поэтому у меня всегда есть доступный токен:

<form id="__AjaxAntiForgeryForm" action="#" method="post"> @Html.AntiForgeryToken()</form>

У меня также есть этот метод в моем файле JavaScript utils:

AddAntiForgeryToken = function (data) {
    data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
    return data;
};

Это все работает как ожидалось, и я получаю токен анти-подделки. Мой фактический код проводки:

myPage.saveData = function() {
    var saveUrl = '/exercises/PostData';

    var myData = JSON.stringify(myPage.contextsArrays);

    $.ajax({
        type: 'POST',
        async: false,
        url: saveUrl,
        data: AddAntiForgeryToken({ myResults: myData }),
        success: function () {
            alert('saved');
        },
        dataType: 'json',
        contentType: "application/json; charset=utf-8"
    });
};

Мой метод действий выглядит следующим образом:

    [HttpPost, ValidateAntiForgeryToken, JsonExceptionFilter]
    public JsonResult PostData(List<ResultsDc> myResults)
    {
        return Json(_apiClient.SubmitResults(myResults));
    }

Я тестировал это с различными реализациями, которые я пытался, и ответ всегда:

{"errorMessage":"The required anti-forgery form field \"__RequestVerificationToken\" is not present."}

Я не размещаю форму, а просто массив данных, но проверяя данные, которые фактически отправляются Json, не выглядит правильно (все кодируется), но имя параметра __RequestVerificationToken присутствует и значение токена также присутствует.

В настоящий момент я довольно смущен всем этим и не могу найти правильный способ отправить токен, чтобы вызвать действие MVC. Если я удалю атрибут ValidateAntiForgeryToken и у вас JSON.stringify(myPage.contextsArrays); как данные, json выглядит корректно (unencoded) и он отлично отображает.

Как получить этот токен, размещенный правильно без формы?

4b9b3361

Ответ 1

Разработчик картона снова ударяет.

Все, что мне нужно было сделать, это удалить:

contentType: "application/json; charset=utf-8"

И делая это (что изменяет тип сделанного post-запроса), чтобы получить содержимое Json фактического свойства данных для правильного привязки к типу модели T DO NOT JSON.stringify() данные.

Ответ 2

(ПРИМЕЧАНИЕ. Я знаю, что это не так уж сильно отличается от того, что уже здесь)

Я понимаю, что это уже ответили, но я сделал это довольно много и добавлю свой ответ на кучу. У меня нет форм на моем сайте, поэтому мне пришлось придумать способы справиться с этим. Много исследований здесь о stackoverflow и некоторых блогах, наконец, дал мне информацию, в которой я нуждался.

Во-первых, здесь мой код в верхней части моей "главной" страницы (MVC Razor):

@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
    @Html.AntiForgeryToken()
}

Затем, во всех вызовах ajax (jQuery), я начинаю вот так:

var token = $("#__AjaxAntiForgeryForm input").val();
var dataObject = {
  __RequestVerificationToken: token,
  myData: "whatever"
};

$.ajax({
  url: '@Url.Action("action", "controller")',
  type: 'POST',
  dataType: 'json',
  data: dataObject,
  error: function (jqXHR, textStatus, errorThrown) {
    console.log("ERROR!");
  },
  success: function (data) {
    //whatever
  }
});

Наконец, в контрольной части вещей это прекрасно работает:

public class controllerController : Controller
{
    [HttpPost]
    [ValidateAntiForgeryToken]
    public JsonResult action (myModel myData)
    {
        return Json(new { Success = "true" }, JsonRequestBehavior.DenyGet);
    }
}

Надеюсь, это поможет другим в одной лодке.

Ответ 3

Проверка жестко запрограммирована для просмотра данных формы.

https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.WebPages/Helpers/AntiXsrf/AntiForgeryTokenStore.cs

    public AntiForgeryToken GetFormToken(HttpContextBase httpContext)
    {
        string value = httpContext.Request.Form[_config.FormFieldName];

Вы можете моделировать отправку формы, следуя определенному формату. Для этого см. Как подражать отправке HTML-формы в запрос POST?

Если вы хотите, вы также можете сделать свой собственный валидатор. Как данные POST JSON для приложения Asp.Net MVC 2 с ValidateAntiForgeryToken объясняют, как это сделать. Это для MVC 2, но вы можете получить от него некоторые идеи.