Как опубликовать данные формы с помощью Fetch 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"

test@example.com
-----------------------------114782935826962
Content-Disposition: form-data; name="password"

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

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

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


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

fetch("api/xxx", {
    body: "email=test@example.com&password=pw",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded",
    },
    method: "post",
}

то, что я хочу, это что-то вроде $("#form").сериализация () в jQuery (без использования jQuery) или способ декодирования mulitpart/form-данных в контроллере. Но спасибо за ответы.

3 ответов


цитата MDN on FormData (выделено мной):

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

так что при использовании FormData вы запираетесь в multipart/form-data. Нет способа отправить FormData объект, как тело и не отправка данных в .

если вы хотите отправить данные как application/x-www-form-urlencoded вам придется либо указать тело в виде строки, закодированной URL, либо передать URLSearchParams себя.


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

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

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


клиент

не устанавливайте заголовок content-type.

// 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; }
}

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

fetch("/path/to/server", {
  method:"POST"
, body:new URLSearchParams("email=test@example.com&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="test@example.com">
  <input name="password" value="pw">
  <input type="submit">
</form>