web-dev-qa-db-fra.com

Comment publier des données de formulaire avec fetch api?

Mon code:

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

J'ai essayé de poster mon formulaire en utilisant fetch api, et le corps qu'il envoie ressemble à ceci:

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

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

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

(Je ne sais pas pourquoi le nombre dans la limite est changé chaque fois qu'il envoie ...)

Je voudrais qu'il envoie les données avec "Content-Type": "application/x-www-form-urlencoded", que dois-je faire? Ou, si je dois y faire face, comment décoder les données de mon contrôleur?


Pour qui répondre à ma question, je sais que je peux le faire avec:

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

Ce que je veux, c'est quelque chose comme $ ("# form"). Serialize () dans jQuery (sans utiliser jQuery) ou la manière de décoder les données mulitpart/form dans le contrôleur. Merci pour vos réponses cependant.

63
Zack

Pour citer MDN sur FormData (souligné par moi):

L’interface FormData permet de construire facilement un ensemble de paires clé/valeur représentant les champs de formulaire et leurs valeurs, qui peuvent ensuite être facilement envoyées à l’aide de la méthode XMLHttpRequest.send(). Il utilise le même format qu'un formulaire utiliserait si le type de codage était défini sur _"multipart/form-data"_.

Ainsi, lorsque vous utilisez FormData, vous vous verrouillez dans _multipart/form-data_. Il n'y a aucun moyen d'envoyer un objet FormData en tant que corps et de ne pas envoyer des données au format _multipart/form-data_.

Si vous souhaitez envoyer les données en tant que _application/x-www-form-urlencoded_, vous devrez soit spécifier le corps en tant que chaîne codée par une URL, soit transmettre un objet URLSearchParams . Ce dernier ne peut malheureusement pas être directement initialisé à partir d'un élément form. Si vous ne voulez pas parcourir vous-même les éléments de formulaire (ce que vous pouviez faire avec HTMLFormElement.elements ), vous pouvez également créer un objet URLSearchParams à partir d'un objet 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(…);
_

Notez qu'il n'est pas nécessaire de spécifier vous-même un en-tête _Content-Type_.


Comme indiqué par monk-time dans les commentaires, vous pouvez également créer URLSearchParams et transmettre directement l'objet FormData au lieu d'ajouter les valeurs dans une boucle:

_const data = new URLSearchParams(new FormData(formElement));
_

Cela a toujours un support expérimental dans les navigateurs, alors assurez-vous de le tester correctement avant de l’utiliser.

79
poke

Client

Ne définissez pas l'en-tête content-type.

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

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

Serveur

Utilisez l'attribut FromForm pour spécifier que la source de liaison est une donnée de formulaire.

[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; }
}
36
regnauld

Vous pouvez définir body sur une instance de URLSearchParams avec une chaîne de requête passée en argument

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>
11
guest271314