Почтовый запрос jQuery ajax на ASP.NET Core MVC с помощью application/json

Я пытаюсь выполнить вызов ajax, используя jQuery.ajax и contentType: 'application/json; charset=utf-8'.

Я создал новый проект для ASP.NET Core MVC с .NET 8.

Это код Javascript:

$('#addPerson').click(function () {
    var person = {
        Name: 'Test1',
        Email: 'Test2'
    };

    $.ajax({
        url: '@Url.Action("AddPerson")',
        contentType: 'application/json; charset=utf-8',
        data: JSON.stringify({ person: person }),
        // data: { person: person },
        type: 'Post',
        success: function (data) {
            
        }
    });
});

Вот метод контроллера и модель:

[HttpPost]
public IActionResult AddPerson(Person person)
{
    return Ok();
}

public class Person
{
    public string Name { get; set; }
    public string Email { get; set; }
}

По какой-то причине свойства человека всегда равны нулю.

Если я прокомментирую строки, показанные ниже, в вызове ajax

contentType: 'application/json; charset=utf-8',
data: JSON.stringify({ person: person }),

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

// data: { person: person },

Кроме того, если я добавлю [FromBody] в свой параметр контроллера и изменю данные на JSON.stringify(person), это все равно будет работать, но я не хочу этого, поскольку во многих случаях мне может потребоваться отправить контроллеру целый объект человека, а затем дополнительные параметры.

Я считаю, что в предыдущих версиях ASP.NET MVC это работало. Я предполагаю, что мне нужно указать сериализатор в program.cs, чтобы он работал. Но я пробовал разные варианты, но безуспешно.

можно уточнить, в чем здесь вопрос? какой тип контента вы хотите использовать и как вы хотите, чтобы контроллер связывал данные?

Lã Ngọc Hải 06.04.2024 09:17

Я хочу использовать приложение/json; charset=utf-8, а данные представляют собой, например, модель представления человека, которую мы видим, и дополнительные параметры. Таким образом, у контроллера будет параметр person и, возможно, другие логические параметры. Я использовал точный пример в asp.net mvc, и он работает. Но в ядре asp.net это не так. Единственный способ заставить это работать — это использовать атрибут [FromBody], который мне не нравится.

Themis Tsiligkoudis 06.04.2024 11:21

Я думаю, что [FromBody] необходим для чтения json. Если вы опустите contentType (по умолчанию «application/x-www-form-urlencoded; charset=UTF-8») и отправите простой объект в data, вы можете избавиться от [FromBody]

Lã Ngọc Hải 07.04.2024 07:15

Да, это то, что я остаюсь и в своем примере. Это работает следующим образом. Но в asp.net mvc это работает в обе стороны без [FromBody]. Интересно, что фундаментально изменилось в ядре .net, и я не могу заставить его работать без [FromBody].

Themis Tsiligkoudis 07.04.2024 07:55
Как конвертировать HTML в PDF с помощью jsPDF
Как конвертировать HTML в PDF с помощью jsPDF
В этой статье мы рассмотрим, как конвертировать HTML в PDF с помощью jsPDF. Здесь мы узнаем, как конвертировать HTML в PDF с помощью javascript.
0
4
1 006
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать JObject из NuGetpackage и использовать пространство имен «Newtonsoft.Json.Linq», но вы все равно можете использовать атрибут [FromBody]:

public IActionResult AddPerson([FromBody] JObject objRequest)
{
    Person person = JsonConvert.DeserializeObject<Person>(objRequest.ToString());
    string phone = objRequest.Value<string>("phone");  // additional field extraction
    // you can add any other fields to objRequest (Request Body) and only those matching fields will be automatically bind to Person object
    return Ok();
}

Я думаю, это выполнимо, но иметь параметры в контроллере гораздо проще. Как я уже сказал, это работает, если не отправлять его с помощью application/json. Мне бы хотелось знать, в чем здесь проблема, потому что я попробовал шаблон для asp.net mvc с .net 4.7.2, и исходный код работает без каких-либо проблем.

Themis Tsiligkoudis 05.04.2024 14:01
Ответ принят как подходящий

Когда вы указываете contentType: 'application/json; charset=utf-8', вы сообщаете серверу, что данные, отправляемые в теле запроса, имеют формат JSON. Связующее устройство модели ASP.NET Core по умолчанию ожидает, что данные JSON будут точно соответствовать параметру метода действия, если вы не используете [FromBody]. В ASP.NET Core атрибут [FromBody] явно указывает связующему устройству модели искать данные в теле запроса. и попробуйте привязать его к параметру метода действия. Без [FromBody] привязка модели просматривает различные источники, включая строку запроса и данные формы, но у нее есть определенные ожидания в отношении тела запроса, которые часто требуют [FromBody] для данных JSON. Ваш вызов AJAX отправляет данные в формате вложенного объекта: { person: person }. Однако ваш метод действия ожидает плоский объект Person. Это причина, по которой ваши свойства кажутся нулевыми, когда вы используете JSON.stringify({ person: person }) без [FromBody].

Вы можете попробовать следующий код, чтобы решить проблему:

 $('#addPerson').click(function () {
    var person = {
        Name: 'Test1',
        Email: 'Test2'
    };

    $.ajax({
        url: '@Url.Action("AddPerson")' + '?additionalParam=true', //additional parameters
        contentType: 'application/json; charset=utf-8',
        data: JSON.stringify(person), // Send person object directly
        type: 'POST',
        success: function (data) {
            // success
        }
    });
});

Контроллер:

[HttpPost]
public IActionResult AddPerson([FromBody] Person person, [FromQuery] bool additionalParam)
{
    // Your Code
    return Ok();
}

Вам нужно использовать [FromBody], чтобы привязать тело JSON к вашей модели.

Я понимаю, что ваш код работает. Мой вопрос заключается в том, можете ли вы выполнить запрос без необходимости создания класса PersonRequest. Можете ли вы добиться того же результата с помощью contentType: 'application/json; charset=utf-8' при наличии метода контроллера: public IActionResult AddPerson (Person person, bool extraParam). Как я уже говорил ранее, мне удается успешно это сделать в asp.net, но не в asp.net-core.

Themis Tsiligkoudis 08.04.2024 15:04

@ThemisTsiligkoudis, не могли бы вы попробовать обновленный код.

Jalpa Panchal 08.04.2024 15:35

Я попробовал ваш код, и он работает. Но мне такой подход тоже не нравится. Я не хочу создавать отдельные классы каждый раз, когда мне нужны дополнительные параметры. Я также не хочу работать с динамическими объектами и десериализацией. Я хочу иметь параметр модели и дополнительные параметры непосредственно в методе контроллера. Это ограничение ядра .net? Потому что, как я уже сказал, в более старой версии asp.net mvc это работает нормально.

Themis Tsiligkoudis 08.04.2024 16:13

@ThemisTsiligkoudis В ASP.NET Core обработка данных JSON требует явного использования атрибута [FromBody] из-за философии дизайна, подчеркивающей четкое разделение задач и больший контроль над привязкой данных. В отличие от более старых версий ASP.NET MVC, связыватель модели ASP.NET Core не определяет источники данных на основе типа контента. Для смешанных типов данных (JSON + другие источники) рекомендуется комбинировать [FromBody] для JSON с другими атрибутами, например [FromQuery], для дополнительных параметров. Этот подход отражает акцент ASP.NET Core на ясности и гибкости.

Jalpa Panchal 10.04.2024 11:06

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