Я хотел бы отправить данные в свой API с помощью AJAX, но у меня возникли проблемы. Я использую Fiddler для тестирования своего API, и я могу правильно опубликовать JSON, но при отправке строки с URL-кодом имени / значения я получаю 400 Bad Request с телом ответа '{"": ["Введенные данные недействительны . "]} '.
В моем окне отладки отображается: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor:Information: Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.SerializableError'.
Публикуемый JSON:
{
"Name": "Test"
}
Размещаемые данные формы:
Name=Test
Это Контроллер и Действие:
[Route("api/[Controller]")]
[ApiController]
public class AccountsController : Controller
{
[HttpPost]
public IActionResult CreateAccount(Account account)
{
//code
}
}
Это класс Account:
public class Account
{
public string Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public string Website { get; set; }
}
Кажется очевидным, что существует проблема во время привязки модели, но данные формы кажутся действительными (я также сгенерировал данные формы с помощью AJAX и также получил 400).
@heretic Я их не выкладываю одновременно. Я делаю два отдельных сообщения: один с JSON, а другой с данными формы. Тип контента автоматически устанавливается скрипачом и совпадает.
Попробуйте использовать почтальона или скрипача, чтобы протестировать Api. У вас api привязка модели нормально, когда вы их используете ??
Убедитесь, что ваш тип запроса установлен на «application / json». Я воспроизвел ваш код, и метод не вызывался с помощью Postman, пока я не установил тип запроса на application / json.
Редактировать: Когда я добавил следующее в заголовки в скрипте, я смог заставить скрипач вызвать мой метод:
Тип содержимого: приложение / json
В своем сообщении Привязка модели JSON POST в ASP.NET Core от 2016 года Эндрю Лок объясняет, что для привязки JSON POST в ASP.NET Core атрибут [FromBody]
должен быть указан в аргументе, например:
[HttpPost]
public IActionResult CreateAccount([FromBody] Account account)
{
// ...
}
С появлением [ApiController]
в ASP.NET Core 2.1 это больше не требуется. Здесь важно то, что этот атрибут эффективно определяет наличие атрибута [FromBody]
, когда связываемый тип является «сложным» (как в вашем примере). Другими словами, это как если бы вы написали код, как я продемонстрировал выше.
В своем посте Эндрю также заявляет следующее:
In some cases you may need to be able to bind both types of data to an action. In that case, you're a little bit stuck, as it won't be possible to have the same end point receive two different sets of data.
Здесь, ссылаясь на оба типа данных, Эндрю имеет в виду как сообщение JSON, так и POST на основе формы. Он продолжает объяснять, как на самом деле добиться желаемого результата. Изменив его пример для своих целей, вам нужно будет сделать что-то вроде следующего:
// Form.
[HttpPost("FromForm")]
public IActionResult CreateAccountFromForm([FromForm] Account account)) =>
DoSomething(account);
// JSON.
[HttpPost("FromBody")]
public IActionResult CreateAccountFromBody(Account account) =>
DoSomething(account);
private IActionResult DoSomething(Account account) {
// ...
}
В примере Эндрю [FromBody]
является явным, а [FromForm]
неявным, но, учитывая влияние, которое [ApiController]
оказывает на значения по умолчанию, модифицированный пример выше меняет положение.
См. Мой ответ здесь для потенциального подхода, который позволяет использовать один и тот же URL-адрес как для FromForm
, так и для FromBody
с использованием настраиваемого IActionConstraint
.
Если вы хотите получить данные формы для заголовка Content-Type: application / x-www-form-urlencoded) на свой контроллер api, вам нужно поместить атрибут [FromForm] в метод действия, например
// POST: api/Create
[HttpPost]
public IActionResult CreateAccount([FromForm] Account account)
{
}
Если вы хотите получить данные формы для заголовка Content-Type: application / json на свой контроллер api, вам нужно поместить атрибут [FromBody] / No в метод действия, например
// POST: api/Create
[HttpPost]
public IActionResult CreateAccount([FromBody] Account account)
{
}
Или же
// POST: api/Create
[HttpPost]
public IActionResult CreateAccount(Account account)
{
}
Install-Package Toycloud.AspNetCore.Mvc.ModelBinding.BodyOrDefaultBinding
Конфиг
services.AddMvc(options =>
{
options.ModelBinderProviders.InsertBodyOrDefaultBinding();
})
Включить для одного параметра
[HttpPost]
public int SaveData([FromBodyOrDefault]DataPoco m)
{
;//
}
https://github.com/shamork/Toycloud.AspNetCore.Mvc.ModelBinding.BodyAndFormBinding
Вы должны опубликовать либо JSON (с соответствующим заголовком Content-Type «application / json»), либо данные формы (с соответствующим Content-Type «application / x-www-form-urlencoded», но не оба сразу.