9

Ich habe eine Spring 3 MVC-Form mit 2 Parametern Ich versuche, an meine Controller-Methode zu senden, und ich bekomme einen 404-Fehler. Das Problem besteht darin, dass das Formular über zwei Schaltflächen zum Senden verfügt, und die Schaltfläche zum Senden, auf die geklickt wird, bestimmt den Wert eines der Parameter. Hier ist meine Form.Spring 3 - Form mit 2 Tasten, Senden von 2 Parametern an die Controller-Methode

<form:form action="/approve/${bulletin.id}" method="post"> 
     <table> 
      <tr> 
       <td colspan="2"><b>From:</b> <c:out value="${bulletin.name}" /></td> 
      </tr> 
      <tr> 
       <td colspan="2"><b>Subject:</b> <c:out 
         value="${bulletin.subject}" /></td> 
      </tr> 
      <tr> 
       <td colspan="2"><b>Date:</b> <c:out value="${bulletin.date}" /> 
        <br></td> 
      </tr> 
      <tr> 
       <td colspan="2"><t:notePrint note="${bulletin.note}" /> <input 
        type="hidden" name="id" value="${bulletin.id}" /></td> 
      </tr> 
      <tr> 
       <td><input type="submit" name="approve" value="Approve" /></td> 
       <td><input type="submit" name="deny" value="Deny" /></td> 
      </tr> 
     </table> 
     <br /> 
    </form:form> 

Hier ist meine Controller-Form.

@RequestMapping(value = "/approve/{id}", method = RequestMethod.POST) 
public String approveBulletin(@RequestParam int id, 
     @RequestParam(required = false, value = "approve") String approve, 
     @RequestParam(required = false, value = "deny") String deny, Model model) { 
    try { 
     if (approve.equalsIgnoreCase("approve")) { 
      bulletinDAO.approveBulletin(id); 
      model.addAttribute("approval", 
        "Your bulletin has been approved."); 
     } 
     if (deny.equalsIgnoreCase("deny")) { 
      bulletinDAO.denyBulletin(id); 
      model.addAttribute("approval", "Your bulletin has been denied."); 
     } 

     List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins(); 
     model.addAttribute("bulletins", bulletins); 
    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
     return "FailurePage"; 
    } 

    return "ApproveBulletin"; 
} 

Antwort

15

Ich habe mein eigenes Problem gelöst. Ich poste meinen Code zugunsten jemand anderen, der diesen Thread mit dem gleichen Problem trifft. Hier ist meine Form.

<form:form action="approve" method="post"> 
    <table> 
     <tr> 
      <td colspan="2"><b>From:</b> <c:out value="${bulletin.name}" /></td> 
     </tr> 
     <tr> 
      <td colspan="2"><b>Subject:</b> <c:out 
        value="${bulletin.subject}" /></td> 
     </tr> 
     <tr> 
      <td colspan="2"><b>Date:</b> <c:out value="${bulletin.date}" /> 
       <br></td> 
     </tr> 
     <tr> 
      <td colspan="2"><t:notePrint note="${bulletin.note}" /> <input 
       type="hidden" name="id" value="${bulletin.id}" /></td> 
     </tr> 
     <tr> 
      <td><input type="submit" name="approve" value="Approve" /></td> 
      <td><input type="submit" name="deny" value="Deny" /></td> 
     </tr> 
    </table> 
    <br /> 
</form:form> 

Hier sind meine Controller-Methoden.

@RequestMapping(value = "/approve", method = RequestMethod.POST, params = { "approve" }) 
public String approve(@RequestParam int id, @RequestParam String approve, Model model) { 
    try { 
     bulletinDAO.approveBulletin(id); 
     model.addAttribute("approval", "Your bulletin has been approved."); 

     List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins(); 
     model.addAttribute("bulletins", bulletins); 
    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
     return "FailurePage"; 
    } 

    return "ApproveBulletin"; 
} 

@RequestMapping(value = "/approve", method = RequestMethod.POST, params = { "deny" }) 
public String deny(@RequestParam int id, @RequestParam String deny, Model model) { 
    try { 
     bulletinDAO.denyBulletin(id); 
     model.addAttribute("approval", "Your bulletin has been denied."); 

     List<Bulletin> bulletins = bulletinDAO.getApprovedBulletins(); 
     model.addAttribute("bulletins", bulletins); 
    } catch (Exception e) { 
     System.out.println(e.getMessage()); 
     return "FailurePage"; 
    } 

    return "ApproveBulletin"; 
} 
+0

Und wie ist es möglich, dies mit MockMVC zu testen? –

+0

Dies wurde nicht mit MockMVC getestet. Dies wurde mit der Anwendung in Tomcat getestet, wie ein Benutzer sie normalerweise verwenden würde. –

9

Ihre Form des action wird auf "/ genehmigen" noch der Controller-Mapping ist "/ genehmigen/{Aktion}/{id}"; Das Dispatcher-Servlet hat keine Möglichkeit, die Verbindung zwischen diesen beiden herzustellen.

Auch wenn die Methode richtig wäre es abgebildet war nicht, was Sie erwarten, dass es zu tun: Sie verwirren action und input und was sie entsprechen in der HTTP-Anforderung.

action legt die URL der Formularanforderung fest, in Ihrem Fall ist es "/approve". Jedes <input> des Elements name Parameter werden verwendet, um HTTP-Parameter mit dem Wert von value hinzufügen, so dass die Anforderung würde eine Kombination von:

  • id=${id} (alle Anfragen)
  • approve=Approve (wenn Benutzer geklickt "genehmigen")
  • deny=Deny (wenn der Benutzer „verweigern“ geklickt)

So behandeln Sie diese beiden Fälle die Signatur geändert werden sollte, der Beherrscher um so etwas wie folgt aus:

@RequestMapping(value = "/approve", method = RequestMethod.POST) 
public String approveBulletin(@RequestParam int id, 
      @RequestParam(required=false, defaultValue="") String approve, 
      @RequestParam(required=false, defaultValue="") String deny, 
      Model model) { 
    if (approve.equals("Approve")) { 
     // user clicked "approve" 
    } else if (deny.equals("Deny")) { 
     // user clicked "deny"    
    } else { 
     throw new IllegalArgumentException("Need either approve or deny!"); 
    } 

    // (...) 
} 

Aber ich würde eher vorschlagen, die Parameter der Senden-Schaltflächen zu ändern:

<td><input type="submit" name="approveParam" value="approveVal" /></td> 
<td><input type="submit" name="approveParam" value="denyVal" /></td> 

diese Weise können Sie immer genau zwei Parameter erhalten: id und approve, dann können Sie einfach überprüfen sie den Wert von approve zu sehen, ob es sich um eine „genehmigen“ oder „verweigern“ war:

public String approveBulletin(@RequestParam int id, 
     @RequestParam(value = "approveParam") String approveOrDeny, 
     Model model) { 
    if (approveOrDeny.equalsIgnoreCase("approveVal")) { 
     // user clicked "approve" 
    } else if (approveOrDeny.equalsIgnoreCase("denyVal")) { 
     // user clicked "deny" 
    } else { 
     // wrong parameter sent 
    } 

Was hilft bei der Diagnose solcher Probleme (dh. ob es sich um das Client- oder Server-Problem handelt) überprüft die ausgehende Anfrage mithilfe der Web-Tools des Browsers (Firebugs in Firefox, Entwicklertools in Chrome usw.). Sie können die Anfrage einfach erfassen und sehen, was die HTTP-Parameter, URL und Methode waren und vergleichen Sie sie mit Ihren Erwartungen.

+0

Ich habe meinen ursprünglichen Beitrag mit der neuesten Version meines Codes aktualisiert, nach Ihren Vorschlägen. Die ID wird jetzt übergeben, aber nicht der Wert der Schaltfläche, auf die ich geklickt habe. –

+0

Können Sie bestätigen, ob in der Anfrage der Parameter "Genehmigen" oder "Verweigern" angezeigt wird? (mit Ihren Browser-Tools) Ich habe gerade getestet, dass es in einem vereinfachten Formular den Wert der Schaltfläche korrekt sendet. – kryger

+0

Ich habe gerade den Parameter in Firebug gefunden. Unter Net/All/Post sehe ich folgendes: id =% 25% 7Bid% 7D & approve = Genehmigen. Wie soll ich den Code umschreiben? –