Проводка 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) и он отлично отображает.
Как получить этот токен, размещенный правильно без формы?
Ответы
Ответ 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, но вы можете получить от него некоторые идеи.