web-dev-qa-db-fra.com

État HTTP 405 - La méthode de demande «POST» n'est pas prise en charge (Spring MVC)

Je reçois cette erreur: HTTP Status 405 - Request method 'POST' not supported

Ce que j'essaie de faire est de créer un formulaire avec une liste déroulante qui sera remplie en fonction de l'autre valeur sélectionnée dans une autre boîte déroulante. Par exemple, lorsque je sélectionne un nom dans la zone customerName, la fonction onChange dans la page .jsp doit être exécutée et la page envoyée puis rechargée avec les valeurs correspondantes dans la customerCountry boîte.

mais j'obtiens cette erreur HTTP Status 405. J'ai recherché une solution sur Internet, mais je n'ai rien trouvé qui puisse m'aider. Voici les parties pertinentes de mon code:

partie de la page jsp

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Insert title here</title>
            <style>
            .error { color: red; }
            </style>

        <script>
            function repopulate(){  
                document.deliveryForm.submit();
            }

            function setFalse(){
                document.getElementById("hasId").value ="false";
                document.deliveryForm.submit();
                // document.submitForm.submit(); (This was causing the error)

            }
        </script>

    </head>
    <body>

        <h1>Create New Delivery</h1>

        <c:url var="saveUrl" value="/test/delivery/add" />
        <form:form modelAttribute="deliveryDtoAttribute" method="POST" action="${saveUrl}" name="deliveryForm">
            <table>


                <tr>
                    <td><form:hidden id="hasId" path="hasCustomerName" value="true"/></td>
                </tr>

                <tr>
                    <td>Customer Name</td>
                    <td><form:select path="customerName" onChange="repopulate()">
                        <form:option value="" label="--- Select ---" />
                        <form:options items="${customerNameList}" />
                        </form:select>
                    </td>
                    <td><form:errors path="customerName" cssClass="error" /></td>
                </tr>

                <tr>
                    <td>Customer Country</td>
                    <td><form:select path="customerCountry">
                        <form:option value="" label="--- Select ---" />
                        <form:options items="${customerCountryList}" />
                        </form:select>
                    </td>
                    <td><form:errors path="customerCountry" cssClass="error" /></td>
                </tr>

        </form:form>

        <form:form name="submitForm">
        <input type="button" value="Save" onClick="setFalse()"/>
        </form:form>

    </body>
</html>

partie du contrôleur:

@RequestMapping(value = "/add", method = RequestMethod.GET)
    public String getDelivery(ModelMap model) {
        DeliveryDto deliveryDto = new DeliveryDto();

        model.addAttribute("deliveryDtoAttribute", deliveryDto);
        model.addAttribute("customerNameList",
                customerService.listAllCustomerNames());
        model.addAttribute("customerCountryList", customerService
                    .listAllCustomerCountries(deliveryDto.getCustomerName()));
        return "new-delivery";
    }

    // I want to enter this method if hasId=true which means that a value in the CustomerName 
    // drop down list was selected. This should set the CountryList to the corresponding values 
    // from the database. I want this post method to be triggered by the onChange in the jsp page

    @RequestMapping(value = "/add", method = RequestMethod.POST, params="hasCustomerName=true")
    public String postDelivery(
            @ModelAttribute("deliveryDtoAttribute") DeliveryDto deliveryDto,
            BindingResult result, ModelMap model) {


            model.addAttribute("deliveryDtoAttribute", deliveryDto);

            model.addAttribute("customerNameList",
                    customerService.listAllCustomerNames());
            model.addAttribute("customerCountryList", customerService
                    .listAllCustomerCountries(deliveryDto.getCustomerName()));

            return "new-delivery";
    }

    // This next post method should only be entered if the save button is hit in the jsp page

    @RequestMapping(value = "/add", method = RequestMethod.POST, params="hasCustomerName=false")
    public String postDelivery2(
            @ModelAttribute("deliveryDtoAttribute") @Valid DeliveryDto deliveryDto,
            BindingResult result, ModelMap model) {

        if (result.hasErrors()) {

            model.addAttribute("deliveryDtoAttribute", deliveryDto);

            model.addAttribute("customerNameList",
                    customerService.listAllCustomerNames());
            model.addAttribute("customerCountryList", customerService
                    .listAllCustomerCountries(deliveryDto.getCustomerName()));

            return "new-delivery";
        } else {

            Delivery delivery = new Delivery();

            //Setters to set delivery values

            return "redirect:/mis/home";
        }

    }

Comment se fait-il que j'obtienne cette erreur? Toute aide serait très appréciée! Merci

EDIT: Modifié hasId en hasCustomerName. Je reçois toujours le HTTP Status 405 - Request method 'POST' not supported erreur cependant.

EDIT2: A mis en commentaire la ligne de la fonction setFalse à l'origine de l'erreur

// RÉ

24
dlinx90

J'ai trouvé le problème à l'origine de l'erreur HTTP.

Dans la fonction setFalse() déclenchée par le bouton Enregistrer, mon code essayait de soumettre le formulaire qui contenait le bouton.

        function setFalse(){
            document.getElementById("hasId").value ="false";
            document.deliveryForm.submit();
            document.submitForm.submit();

quand je retire la document.submitForm.submit(); ça marche:

        function setFalse(){
            document.getElementById("hasId").value ="false";
            document.deliveryForm.submit()

@Roger Lindsjö Merci d'avoir repéré mon erreur là où je ne transmettais pas le bon paramètre!

3
dlinx90

Je ne sais pas si cela aide, mais j'ai eu le même problème.

Vous utilisez springSecurityFilterChain avec la protection CSRF. Cela signifie que vous devez envoyer un jeton lorsque vous envoyez un formulaire via POST request. Essayez d'ajouter la prochaine entrée à votre formulaire:

<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
21
Ashish

Vérifiez si vous renvoyez un @ResponseBody ou un @ResponseStatus

J'avais un problème similaire. Mon contrôleur ressemblait à ça:

@RequestMapping(value="/user", method = RequestMethod.POST)
public String updateUser(@RequestBody User user){
    return userService.updateUser(user).getId();
}

Lors d'un appel avec une demande POST, j'ai toujours l'erreur suivante:

Statut HTTP 405 - La méthode de demande 'POST' n'est pas prise en charge

Après un certain temps, j'ai compris que la méthode était en fait appelée, mais parce qu'il n'y a pas de @ResponseBody et pas de @ResponseStatus Spring MVC soulève l'erreur.

Pour résoudre ce problème, ajoutez simplement un @ResponseBody

@RequestMapping(value="/user", method = RequestMethod.POST)
public @ResponseBody String updateUser(@RequestBody User user){
    return userService.updateUser(user).getId();
}

ou un @ResponseStatus à votre méthode.

@RequestMapping(value="/user", method = RequestMethod.POST)
@ResponseStatus(value=HttpStatus.OK)
public String updateUser(@RequestBody User user){
    return userService.updateUser(user).getId();
}
16
RenRen

Vous devrez peut-être modifier la ligne

@RequestMapping(value = "/add", method = RequestMethod.GET)

à

@RequestMapping(value = "/add", method = {RequestMethod.GET,RequestMethod.POST})
5
harshit

Le problème est que votre contrôleur attend un paramètre hasId = false ou hasId = true, mais vous ne le transmettez pas. Votre champ masqué a l'ID hasId mais est passé comme hasCustomerName, donc aucun mappage ne correspond.

Modifiez le chemin du champ masqué en hasId ou le paramètre de mappage pour attendre hasCustomerName = true ou hasCustomerName = false.

3
Roger Lindsjö