ASPNET CORE Ajax Post приводит к 400 неверным запросам

Я работаю над ASP.NET Zero, который построен на ASP.NET Core. Я получал неверную ошибку запроса, когда использовал элемент управления KendoUI Upload на одной из своих страниц. После долгих исследований и расследований я понял, что запрос HTTP POST Ajax не работает с ошибкой 400 неверного запроса. В моих примерах кода ниже есть некоторые строки с комментариями для других тестируемых мной сценариев. Ни одна из существующих публикаций в переполнении стека не решила мою проблему. I Ниже мой вызов ajax:

 $.ajax({
            url: "/test/TestCall",
            type: 'Post',
           /* data: JSON.stringify({ "Param1": "test" }),
            dataType:"json",
            processData: false,  */// tell jQuery not to process the data
            contentType: "application/json",  // tell jQuery not to set contentType
            success: function (result) {
                var res = result;
            },
            error: function (jqXHR) {
                var z = 3;
            },
            complete: function (jqXHR, status) {
                var x = 10;
            }
        });

Мой код контроллера: Я также пробовал не расширять MyTestProjectControllerBase и просто использовать базовый класс Controller. Это не работает.

public class TestController : MyTestProjectControllerBase
{
    public IActionResult Index()
    {
        return View();
    }

   [HttpPost]
    public ActionResult TestCall()
    {
        //return Content("Name is:" );
        return new ContentResult() { Content = "test" };
    }
}

Что мне не хватает? Я пробовал пользоваться почтальоном и вижу дополнительную информацию 'Запрос не может быть выполнен из-за неправильного синтаксиса'

не мог понять этого, потратив добрые 8 часов на эту проблему. Не уверен, связана ли проблема с ядром Asp.net или нулевым asp.net. Приветствуются любые указатели.

Обновление после проверки комментариев shyju: Файл Startup.cs содержит следующий код, который включает AntiForgeryTokenAttribute.

 services.AddMvc(options =>
        {
            options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
        }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Обновления для вызова и просмотра ajax на основе ответа shyju:

  $("#backBtn").on("click", function (e) {
        var t = $("input[name='__RequestVerificationToken']").val();
        $.ajax({
            url: "/test/TestCall",
            type: 'Post',
           /* data: JSON.stringify({ "Param1": "test" }),
            dataType:"json",
            processData: false,  */
            contentType: "application/json",  
            headers: {
                "RequestVerificationToken": t
            },
            success: function (result) {
                var res = result;
            },
            error: function (jqXHR) {
                var z = 3;
            },
            complete: function (jqXHR, status) {
                var x = 10;
            }
        });
    });

Мое мнение сейчас выглядит так: удалена остальная часть html

<div id = "container">
    @Html.AntiForgeryToken()
    <div class = "k-edit-field label">Vendor Name</div>
</div

С кодом, которым вы поделились, он не должен выдавать ответ 400. Я просто скопировал и вставил ваш код в локальный проект, и он мне вернул 200 OK. Похоже, вы не делитесь кодом, который вызывает ответ 400. Есть ли у вашего метода действия атрибут ValidateAntiForgeryToken?

Shyju 07.01.2019 19:46

Нет. В этом проекте много существующих файлов. но в созданном мной контроллере нет ничего, кроме того, что я здесь скопировал. ValidateAntiForgeryToken отсутствует в моем методе действия. Вы тестировали мой код на ядре aspnet?

LMKN 07.01.2019 19:55

привет, я только что нашел ValidateAntiForgeryToken во всем решении. В startup.cs есть следующий код services.AddMvc (options => {options.Filters.Add (new AutoValidateAntiforgeryTokenAttribute ());}). SetCompatibilityVersion (CompatibilityVersion.Version_2_1) ‌;

LMKN 07.01.2019 19:58

можешь добавить это к вопросу. Я опубликую решение сейчас

Shyju 07.01.2019 20:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
4
10 714
4

Ответы 4

Похоже, у вас глобально применен фильтр AutoValidateAntiforgeryTokenAttribute. Это означает, что когда вызывается метод действия HTTP Post (нормальный или ajax), фреймворк проверяет отправленные данные запроса, и если он не находит действительный токен защиты от подделки (заголовок RequestVerificationToken), он будет считаться неправильным запросом и 400 ответ будет отправлен обратно.

Чтобы решить эту проблему, вы можете явно прочитать значение скрытого ввода __RequestVerificationToken (сгенерированное помощником тега формы) и отправить его в заголовках запроса ajax.

var t = $("input[name='__RequestVerificationToken']").val();

$.ajax({
    url: "/test/TestCall",
    type: 'Post',
    headers:
    {
        "RequestVerificationToken": t
    },
    success: function (result) {
        alert("Success");
        var res = result;
    },
    error: function (jqXHR) {
        var z = 3;
    },
    complete: function (jqXHR, status) {
        var x = 10;
    }
});

Вы можете сделать код более надежным, внедрив реализацию IAntiforgery в представление / страницу и используя метод GetAndStoreTokens.

Добавьте это к своему обзору

@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
    return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}

и вызовите эту функцию GetAntiXsrfRequestToken, чтобы получить значение в вашем javascript (который находится внутри файла представления)

headers:
{
    "RequestVerificationToken": '@GetAntiXsrfRequestToken()'
},

Спасибо за помощь. Это не устранило проблему. однако, если я закомментирую глобальный фильтр для тестирования, это позволит пройти почтовому запросу. Вы правильно определили проблему. но решение по какой-то причине не работает. Я вижу токен, сгенерированный и переданный в вызов ajax. обновит новый вызов ajax в вопросе

LMKN 07.01.2019 20:21

Отправляет ли он необходимое значение заголовка? Пробовал ваш код и отлично работал у меня.

Shyju 07.01.2019 20:56

Я зарегистрировался на вкладке сети в Chrome; в заголовке запроса установлен токен RequestVerificationToken. Есть ли еще что-нибудь, что мне нужно проверить?

LMKN 07.01.2019 21:17

Есть ли у вас какие-либо другие фильтры на стороне вашего сервера, которые могут возвращать ответ 400?

Shyju 07.01.2019 21:18

Точно сказать не могу. что мне искать? его исходный код asp.net zero имеет много файлов

LMKN 07.01.2019 21:31

Других фильтров в startup.cs не вижу. буду продолжать поиск

LMKN 07.01.2019 21:46

Спасибо за это объяснение @Shyju. Это помогло мне решить ту же проблему. Однако я не понимаю того факта, что мой вызов ajax работал неделями без использования каких-либо заголовков для указания токена. Внезапно сегодня я получил ошибку http 400. Это почему? Я не делал никаких изменений относительно токена ни в контроллере, ни в модели, ни в представлении.

Francois 28.04.2020 21:52

Попробуйте указать в шапке с X-XSRF-TOKEN.

Для ABP Intercept XMLHttpRequest.

Since all libraries use JavaScript's native AJAX object, XMLHttpRequest, you can define a simple interceptor to add the token to the header:

(function (send) {
    XMLHttpRequest.prototype.send = function (data) {
        this.setRequestHeader(abp.security.antiForgery.tokenHeaderName, abp.security.antiForgery.getToken());
        return send.call(this, data);
    };
})(XMLHttpRequest.prototype.send);

Для abp.security.antiForgery.tokenHeaderName значение по умолчанию - X-XSRF-TOKEN.

В Core - убедитесь, что ваш тег <form> включает method = "post".

Этот метод требуется для вызова помощника тега формы, который автоматически добавляет в форму токен защиты от подделки. (Я случайно отказался от этого метода и не заметил, потому что публиковал его с помощью ajax.)

В Net Core RazorPages вам нужно будет передать AntiForgeryToken с помощью запроса JQuery Ajax Post. если у вас есть тег формы с Method = Post, вам не нужно беспокоиться об его отправке.

$.ajax({
    type:"post",
    url:"?Handler=Update",
    dataType:"json",
    beforeSend: function(xhr){
      xhr.setRequestHeader("XSRF-TOKEN",
        $('input:hidden[name = "__RequestVerificationToken"]').val());
    },
    success: function(result){
      // do something
    }
});

Затем на вашей странице Razor

@using Microsoft.AspNetCore.Antiforgery
@inject IAntiforgery antiforgery
@{
   var token = antoforgery.GetAndStoreTokens(HttpContext).RequestToken;
}

Не забудьте добавить

@Html.AntiForgeryToken()

Затем в вашем StartUp.cs внутри метода ConfigureServices добавьте

services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");

Другие вопросы по теме