Mi código:
fetch("api/xxx", { body: new FormData(document.getElementById("form")), headers: { "Content-Type": "application/x-www-form-urlencoded", // "Content-Type": "multipart/form-data", }, method: "post", }Traté de publicar mi formulario usando fetch api, y el cuerpo que envía es como:
-----------------------------114782935826962 Content-Disposition: form-data; name="email" test@example.com -----------------------------114782935826962 Content-Disposition: form-data; name="password" pw -----------------------------114782935826962--(No sé por qué el número en el límite cambia cada vez que envía...)
Me gustaría enviar los datos con "Content-Type": "application/x-www-form-urlencoded", ¿qué debo hacer? O si solo tengo que lidiar con eso, ¿cómo decodifico los datos en mi controlador?
A quien responda mi pregunta, se que puedo hacerlo con:
fetch("api/xxx", { body: "email=test@example.com&password=pw", headers: { "Content-Type": "application/x-www-form-urlencoded", }, method: "post", }Lo que quiero es algo como $("#form").serialize() en jQuery (sin usar jQuery) o la forma de decodificar mulitpart/form-data en el controlador. Gracias por sus respuestas sin embargo.
Para citar MDN en FormData (énfasis mío):
La interfaz
FormDataproporciona una forma de construir fácilmente un conjunto de pares clave/valor que representan campos de formulario y sus valores, que luego se pueden enviar fácilmente mediante el métodoXMLHttpRequest.send(). Utiliza el mismo formato que usaría un formulario si el tipo de codificación se estableciera en"multipart/form-data".
Entonces, cuando usa FormData , se encierra en multipart/form-data . No hay forma de enviar un objeto FormData como el cuerpo y no enviar datos en el formato multipart/form-data .
Si desea enviar los datos como application/x-www-form-urlencoded , deberá especificar el cuerpo como una cadena codificada en URL o pasar un objeto URLSearchParams . Lamentablemente, este último no se puede inicializar directamente desde un elemento de form . Si no desea iterar a través de los elementos de su formulario usted mismo (lo que podría hacer usando HTMLFormElement.elements ), también puede crear un objeto URLSearchParams a partir de un objeto 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(…); Tenga en cuenta que no necesita especificar un encabezado Content-Type usted mismo.
Como señaló monk-time en los comentarios, también puede crear URLSearchParams y pasar el objeto FormData directamente, en lugar de agregar los valores en un bucle:
const data = new URLSearchParams(new FormData(formElement));Sin embargo, esto todavía tiene cierto soporte experimental en los navegadores, así que asegúrese de probarlo correctamente antes de usarlo.
Cliente
No establezca el encabezado de tipo de contenido.
// Build formData object. let formData = new FormData(); formData.append('name', 'John'); formData.append('password', 'John123'); fetch("api/SampleData", { body: formData, method: "post" });Servidor
Utilice el atributo FromForm para especificar que el origen del enlace son datos de formulario.
[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; } }Puede establecer body en una instancia de URLSearchParams con una cadena de consulta pasada como argumento
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>