Я пытаюсь выполнить вызов 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
, чтобы он работал. Но я пробовал разные варианты, но безуспешно.
Я хочу использовать приложение/json; charset=utf-8, а данные представляют собой, например, модель представления человека, которую мы видим, и дополнительные параметры. Таким образом, у контроллера будет параметр person и, возможно, другие логические параметры. Я использовал точный пример в asp.net mvc, и он работает. Но в ядре asp.net это не так. Единственный способ заставить это работать — это использовать атрибут [FromBody], который мне не нравится.
Я думаю, что [FromBody] необходим для чтения json. Если вы опустите contentType
(по умолчанию «application/x-www-form-urlencoded; charset=UTF-8») и отправите простой объект в data
, вы можете избавиться от [FromBody]
Да, это то, что я остаюсь и в своем примере. Это работает следующим образом. Но в asp.net mvc это работает в обе стороны без [FromBody]. Интересно, что фундаментально изменилось в ядре .net, и я не могу заставить его работать без [FromBody].
Вы можете использовать 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, и исходный код работает без каких-либо проблем.
Когда вы указываете 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.
@ThemisTsiligkoudis, не могли бы вы попробовать обновленный код.
Я попробовал ваш код, и он работает. Но мне такой подход тоже не нравится. Я не хочу создавать отдельные классы каждый раз, когда мне нужны дополнительные параметры. Я также не хочу работать с динамическими объектами и десериализацией. Я хочу иметь параметр модели и дополнительные параметры непосредственно в методе контроллера. Это ограничение ядра .net? Потому что, как я уже сказал, в более старой версии asp.net mvc это работает нормально.
@ThemisTsiligkoudis В ASP.NET Core обработка данных JSON требует явного использования атрибута [FromBody]
из-за философии дизайна, подчеркивающей четкое разделение задач и больший контроль над привязкой данных. В отличие от более старых версий ASP.NET MVC, связыватель модели ASP.NET Core не определяет источники данных на основе типа контента. Для смешанных типов данных (JSON + другие источники) рекомендуется комбинировать [FromBody]
для JSON с другими атрибутами, например [FromQuery]
, для дополнительных параметров. Этот подход отражает акцент ASP.NET Core на ясности и гибкости.
можно уточнить, в чем здесь вопрос? какой тип контента вы хотите использовать и как вы хотите, чтобы контроллер связывал данные?