the - incluir antiforgerytoken en ajax publicar ASP.NET MVC
the required anti forgery form field__ requestverificationtoken is not present (7)
Estoy teniendo problemas con AntiForgeryToken con ajax. Estoy usando ASP.NET MVC 3. Probé la solución en llamadas jQuery Ajax y Html.AntiForgeryToken () . Usando esa solución, el token ahora está siendo pasado:
var data = { ... } // with token, key is ''__RequestVerificationToken''
$.ajax({
type: "POST",
data: data,
datatype: "json",
traditional: true,
contentType: "application/json; charset=utf-8",
url: myURL,
success: function (response) {
...
},
error: function (response) {
...
}
});
Cuando [ValidateAntiForgeryToken]
atributo [ValidateAntiForgeryToken]
solo para ver si los datos (con el token) se pasan como parámetros al controlador, puedo ver que se están transfiriendo. Pero, por alguna razón, el A required anti-forgery token was not supplied or was invalid.
el mensaje aún aparece cuando devuelvo el atributo.
¿Algunas ideas?
EDITAR
El antiforgerytoken se genera dentro de un formulario, pero no estoy usando una acción de envío para enviarlo. En cambio, estoy obteniendo el valor del token usando jquery y luego tratando de ajax publicar eso.
Aquí está el formulario que contiene el token y está ubicado en la página maestra superior:
<form id="__AjaxAntiForgeryForm" action="#" method="post">
@Html.AntiForgeryToken()
</form>
¡es tan simple! cuando usa @Html.AntiForgeryToken()
en su código html significa que el servidor ha firmado esta página y cada solicitud que se envía al servidor desde esta página en particular tiene un letrero que no permite el envío de una solicitud falsa por parte de los hackers. entonces, para que el servidor autentique esta página, debe seguir dos pasos:
1. Enviar un parámetro llamado __RequestVerificationToken
y obtener sus códigos de uso de valor a continuación:
<script type="text/javascript">
function gettoken() {
var token = ''@Html.AntiForgeryToken()'';
token = $(token).val();
return token;
}
</script>
por ejemplo, tomar una llamada ajax
$.ajax({
type: "POST",
url: "/Account/Login",
data: {
__RequestVerificationToken: gettoken(),
uname: uname,
pass: pass
},
dataType: ''json'',
contentType: ''application/x-www-form-urlencoded; charset=utf-8'',
success: successFu,
});
y el paso 2 simplemente decora tu método de acción por [ValidateAntiForgeryToken]
En Asp.Net MVC cuando usa @Html.AntiForgeryToken()
Razor crea un campo de entrada oculto con el nombre __RequestVerificationToken
para almacenar tokens. Si desea escribir una implementación de AJAX, tiene que obtener este token y pasarlo como un parámetro al servidor para que pueda ser validado.
Paso 1: obtener la ficha
var token = $(''input[name="`__RequestVerificationToken`"]'').val();
Paso 2: Pase el token en la llamada AJAX
function registerStudent() {
var student = {
"FirstName": $(''#fName'').val(),
"LastName": $(''#lName'').val(),
"Email": $(''#email'').val(),
"Phone": $(''#phone'').val(),
};
$.ajax({
url: ''/Student/RegisterStudent'',
type: ''POST'',
data: {
__RequestVerificationToken:token,
student: student,
},
dataType: ''JSON'',
contentType:''application/x-www-form-urlencoded; charset=utf-8'',
success: function (response) {
if (response.result == "Success") {
alert(''Student Registered Succesfully!'')
}
},
error: function (x,h,r) {
alert(''Something went wrong'')
}
})
};
Nota : El tipo de contenido debe ser ''application/x-www-form-urlencoded; charset=utf-8''
''application/x-www-form-urlencoded; charset=utf-8''
He subido el proyecto a Github; puedes descargarlo y probarlo.
Ha especificado incorrectamente el contentType
a application/json
.
Aquí hay un ejemplo de cómo esto podría funcionar.
Controlador:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(string someValue)
{
return Json(new { someValue = someValue });
}
}
Ver:
@using (Html.BeginForm(null, null, FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}
<div id="myDiv" data-url="@Url.Action("Index", "Home")">
Click me to send an AJAX request to a controller action
decorated with the [ValidateAntiForgeryToken] attribute
</div>
<script type="text/javascript">
$(''#myDiv'').submit(function () {
var form = $(''#__AjaxAntiForgeryForm'');
var token = $(''input[name="__RequestVerificationToken"]'', form).val();
$.ajax({
url: $(this).data(''url''),
type: ''POST'',
data: {
__RequestVerificationToken: token,
someValue: ''some value''
},
success: function (result) {
alert(result.someValue);
}
});
return false;
});
</script>
Intenté mucho workarrounds y ninguno de ellos funcionó para mí. La excepción fue "El campo de formulario antifalsificación requerido" __RequestVerificationToken ".
Lo que me ayudó fue cambiar de .ajax a .post:
$.post(
url,
$(formId).serialize(),
function (data) {
$(formId).html(data);
});
Sé que esta es una vieja pregunta. Pero agregaré mi respuesta de todos modos, podría ayudar a alguien como yo.
Si no desea procesar el resultado de la acción posterior del controlador, como llamar al método LoggOff
del controlador de Accounts
, podría hacer la siguiente versión de la respuesta de @DarinDimitrov:
@using (Html.BeginForm("LoggOff", "Accounts", FormMethod.Post, new { id = "__AjaxAntiForgeryForm" }))
{
@Html.AntiForgeryToken()
}
<!-- this could be a button -->
<a href="#" id="ajaxSubmit">Submit</a>
<script type="text/javascript">
$(''#ajaxSubmit'').click(function () {
$(''#__AjaxAntiForgeryForm'').submit();
return false;
});
</script>
Otro enfoque (menos javascript), que lo hice, es algo como esto:
Primero, un helper Html
public static MvcHtmlString AntiForgeryTokenForAjaxPost(this HtmlHelper helper)
{
var antiForgeryInputTag = helper.AntiForgeryToken().ToString();
// Above gets the following: <input name="__RequestVerificationToken" type="hidden" value="PnQE7R0MIBBAzC7SqtVvwrJpGbRvPgzWHo5dSyoSaZoabRjf9pCyzjujYBU_qKDJmwIOiPRDwBV1TNVdXFVgzAvN9_l2yt9-nf4Owif0qIDz7WRAmydVPIm6_pmJAI--wvvFQO7g0VvoFArFtAR2v6Ch1wmXCZ89v0-lNOGZLZc1" />
var removedStart = antiForgeryInputTag.Replace(@"<input name=""__RequestVerificationToken"" type=""hidden"" value=""", "");
var tokenValue = removedStart.Replace(@""" />", "");
if (antiForgeryInputTag == removedStart || removedStart == tokenValue)
throw new InvalidOperationException("Oops! The Html.AntiForgeryToken() method seems to return something I did not expect.");
return new MvcHtmlString(string.Format(@"{0}:""{1}""", "__RequestVerificationToken", tokenValue));
}
eso devolverá una cadena
__RequestVerificationToken:"P5g2D8vRyE3aBn7qQKfVVVAsQc853s-naENvpUAPZLipuw0pa_ffBf9cINzFgIRPwsf7Ykjt46ttJy5ox5r3mzpqvmgNYdnKc1125jphQV0NnM5nGFtcXXqoY3RpusTH_WcHPzH4S4l1PmB8Uu7ubZBftqFdxCLC5n-xT0fHcAY1"
para que podamos usarlo así
$(function () {
$("#submit-list").click(function () {
$.ajax({
url: ''@Url.Action("SortDataSourceLibraries")'',
data: { items: $(".sortable").sortable(''toArray''), @Html.AntiForgeryTokenForAjaxPost() },
type: ''post'',
traditional: true
});
});
});
¡Y parece funcionar!
function DeletePersonel(id) { var data = new FormData(); data.append("__RequestVerificationToken", "@HtmlHelper.GetAntiForgeryToken()"); $.ajax({ type: ''POST'', url: ''/Personel/Delete/'' + id, data: data, cache: false, processData: false, contentType: false, success: function (result) { } }); } public static class HtmlHelper { public static string GetAntiForgeryToken() { System.Text.RegularExpressions.Match value = System.Text.RegularExpressions.Regex.Match(System.Web.Helpers.AntiForgery.GetHtml().ToString(), "(?:value=/")(.*)(?:/")"); if (value.Success) { return value.Groups[1].Value; } return ""; } }