Как отправить данные формы с помощью api?

Мой код:

fetch("api/xxx", {
    body: new FormData(document.getElementById("form")),
    headers: {
        "Content-Type": "application/x-www-form-urlencoded",
        // "Content-Type": "multipart/form-data",
    },
    method: "post",
}

Я попытался опубликовать свою форму, используя fetch api, и тело, которое оно отправляет, похоже на:

-----------------------------114782935826962
Content-Disposition: form-data; name="email"

[email protected]
-----------------------------114782935826962
Content-Disposition: form-data; name="password"

pw
-----------------------------114782935826962--

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

Я бы хотел, чтобы он отправлял данные с помощью "Content-Type": "application/x-www-form-urlencoded", что мне делать? Или, если мне просто нужно иметь дело с этим, как мне декодировать данные в моем контроллере?


Чтобы ответить на мой вопрос, я знаю, что могу это сделать:

fetch("api/xxx", {
    body: "[email protected]&password=pw",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded",
    },
    method: "post",
}

Я хочу что-то вроде $ ("# form"). Serialize() в jQuery (без использования jQuery) или способ декодирования mulitpart/form-data в контроллере. Спасибо за ваши ответы.

Ответ 1

Чтобы FormData MDN на FormData (выделение мое):

Интерфейс FormData предоставляет возможность легко построить набор пар ключ/значение, представляющих поля формы и их значения, которые затем могут быть легко отправлены с использованием метода XMLHttpRequest.send(). Он использует тот же формат, который форма использовала бы, если для типа кодировки были установлены "multipart/form-data".

Поэтому при использовании FormData вы блокируете себя в multipart/form-data. FormData отправить объект FormData в качестве тела и не отправлять данные в формате multipart/form-data.

Если вы хотите отправить данные в виде application/x-www-form-urlencoded вам нужно будет указать тело как строку с кодировкой URL-адреса или передать объект URLSearchParams. Последние, к сожалению, не могут быть непосредственно инициализированы из элемента form. Если вы не хотите выполнять итерацию через свои элементы формы (что вы можете сделать с помощью HTMLFormElement.elements), вы также можете создать объект URLSearchParams из объекта FormData:

const data = new URLSearchParams();
for (const pair of new FormData(formElement)) {
    data.append(pair[0], pair[1]);
}

fetch(url, {
    method: 'post',
    body: data,
})
.then(…);

Обратите внимание, что вам не нужно указывать заголовок Content-Type самостоятельно.


Как отмечается в комментариях к моменту времени, вы также можете создавать URLSearchParams и передавать объект FormData напрямую, а не FormData значения в цикле:

const data = new URLSearchParams(new FormData(formElement));

Тем не менее, в браузерах все еще есть экспериментальная поддержка, поэтому прежде чем использовать его, обязательно проверьте это правильно.

Ответ 2

клиент

Не устанавливайте заголовок содержимого.

// Build formData object.
let formData = new FormData();
formData.append('name', 'John');
formData.append('password', 'John123');

fetch("api/SampleData",
    {
        body: formData,
        method: "post"
    });

сервер

Используйте атрибут FromForm чтобы указать, что источником привязки являются данные формы.

[Route("api/[controller]")]
public class SampleDataController : Controller
{
    [HttpPost]
    public IActionResult Create([FromForm]UserDto dto)
    {
        return Ok();
    }
}

public class UserDto
{
    public string Name { get; set; }
    public string Password { get; set; }
}

Ответ 3

Вы можете установить body в экземпляр URLSearchParams с строкой запроса, переданной как аргумент

fetch("/path/to/server", {
  method:"POST"
, body:new URLSearchParams("[email protected]&password=pw")
})

document.forms[0].onsubmit = async(e) => {
  e.preventDefault();
  const params = new URLSearchParams([...new FormData(e.target).entries()]);
  // fetch("/path/to/server", {method:"POST", body:params})
  const response = await new Response(params).text();
  console.log(response);
}
<form>
  <input name="email" value="[email protected]">
  <input name="password" value="pw">
  <input type="submit">
</form>