Le type de contenu 'application / x-www-form-urlencoded; charset = UTF-8' n'est pas pris en charge pour @RequestBody MultiValueMap


94

Basé sur la réponse au problème avec x-www-form-urlencoded avec Spring @Controller

J'ai écrit la méthode @Controller ci-dessous

@RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST
            , produces = {"application/json", "application/xml"}
            ,  consumes = {"application/x-www-form-urlencoded"}
    )
     public
        @ResponseBody
        Representation authenticate(@PathVariable("email") String anEmailAddress,
                                    @RequestBody MultiValueMap paramMap)
                throws Exception {


            if(paramMap == null || paramMap.get("password") == null) {
                throw new IllegalArgumentException("Password not provided");
            }
    }

la demande à laquelle échoue avec l'erreur ci-dessous

{
  "timestamp": 1447911866786,
  "status": 415,
  "error": "Unsupported Media Type",
  "exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
  "message": "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
  "path": "/users/usermail%40gmail.com/authenticate"
}

[PS: Jersey était beaucoup plus convivial, mais ne pouvait pas l'utiliser maintenant étant donné les restrictions pratiques ici]


Avez-vous ajouté consumes = {"application / x-www-form-urlencoded"} dans @RequestBody?
shiladitya

1
Comment avez-vous exécuté la demande? ajoutez le code de (js, jquery, curl ou tout ce que vous utilisez).
Nikolay Rusev

J'ai le même problème. Dans mon cas, j'utilise jquery ajax pour publier les données et les données sontJSON.stringify({"ordersToDownload":"00417002"}
Arashsoft

Voici le code que j'utilise:$.ajax({url:"/myurl", type:"POST", data: JSON.stringify({"someAttribute":"someData"}) })
Arashsoft

Réponses:


126

Le problème est que lorsque nous utilisons application / x-www-form-urlencoded , Spring ne le comprend pas comme un RequestBody. Donc, si nous voulons l'utiliser, nous devons supprimer l' annotation @RequestBody .

Ensuite, essayez ce qui suit:

@RequestMapping(value = "/{email}/authenticate", method = RequestMethod.POST,
        consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE, 
        produces = {MediaType.APPLICATION_ATOM_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public @ResponseBody  Representation authenticate(@PathVariable("email") String anEmailAddress, MultiValueMap paramMap) throws Exception {
   if(paramMap == null && paramMap.get("password") == null) {
        throw new IllegalArgumentException("Password not provided");
    }
    return null;
}

Notez que l'annotation @RequestBody a été supprimée

Réponse : La demande de publication HTTP avec le type de contenu application / x-www-form-urlencoded ne fonctionne pas au printemps


Merci! Résout le problème. Maintenant, je me demande comment supprimer explicitement le application/x-www-form-urlencoded?
kholofelo Maloma

1
il n'est pas nécessaire @kholofeloMaloma
Douglas Ribeiro

Si quelqu'un se demandait pourquoi cela fonctionne sans aucune annotation, il semble que Spring gère tous les arguments non annotés comme s'ils avaient @ModelAttribute, even though this behaviour is (sadly) not documented. And @ModelAttribute comprenait x-www-form-urlencoded
cranphin

public ResponseEntity <?> getToken (MultiValueMap paramMap) IllegalArgumentException: incompatibilité de type d'argument
withoutOne

Merci pour l'info! En tant que débutant, je me demande quelle est la raison de ce petit comportement étrange de Spring pour analyser la charge utile et la lier à un objet?
hafan96 le

66

Il semble que maintenant vous pouvez simplement marquer le paramètre de méthode avec @RequestParamet il fera le travail pour vous.

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam Map<String, String> body ) {
  //work with Map
}

18

Ajoutez un en-tête à votre demande pour définir le type de contenu sur application / json

curl -H 'Content-Type: application/json' -s -XPOST http://your.domain.com/ -d YOUR_JSON_BODY

de cette façon, le printemps sait comment analyser le contenu.


Vous devrez peut-être également ajouter un en-tête Accept à votre commande: 'curl -vk -H "Accept: application / json" -H "Content-Type: application / json"' etc.
razvanone

1
pouvez-vous expliquer comment ajouter ce paramètre à mon formulaire HTML?
Osama Al-Banna

8

Au printemps 5

@PostMapping( "some/request/path" )
public void someControllerMethod( @RequestParam MultiValueMap body ) {

    // import org.springframework.util.MultiValueMap;

    String datax = (String) body .getFirst("datax");
}

Oui, avec l'inclusion de consumer = MediaType.APPLICATION_FORM_URLENCODED_VALUE dans la cartographie, vous méritez plus de points monsieur! Merci! Les coutures @RequestParam doivent être requises maintenant pour récupérer MultiValueMap à partir de la demande
NemanjaT

2

Le simple fait de supprimer l' @RequestBodyannotation résout le problème (testé sur Spring Boot 2):

@RestController
public class MyController {

    @PostMapping
    public void method(@Valid RequestDto dto) {
       // method body ...
    }
}

1

J'ai écrit sur une alternative dans cette réponse StackOverflow .

Là, j'ai écrit étape par étape, en expliquant avec du code. Le chemin court:

Premièrement : écrire un objet

Deuxièmement : créer un convertisseur pour mapper le modèle en étendant le AbstractHttpMessageConverter

Troisièmement : dites au printemps d'utiliser ce convertisseur implémentant un WebMvcConfigurer.class remplaçant la méthode configureMessageConverters

Quatrième et dernier: l'utilisation de ce paramètre d'implémentation dans le mappage à l'intérieur de votre contrôleur consomme = MediaType.APPLICATION_FORM_URLENCODED_VALUE et @RequestBody devant votre objet.

J'utilise Spring Boot 2.


0
@PostMapping(path = "/my/endpoint", consumes = { MediaType.APPLICATION_FORM_URLENCODED_VALUE })
public ResponseEntity<Void> handleBrowserSubmissions(MyDTO dto) throws Exception {
    ...
}

Cette façon fonctionne pour moi

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.