简体   繁体   中英

Sending form using Ajax - Spring MVC

I have problems with sending my form using Ajax.

Here is form:

<form method="POST" id="add-card-form" action="${pageContext.request.contextPath}/card/add" class="form-horizontal">
 <select name="type" class="form-control">
    <c:forEach items="${cardTypes}" var="cardType">
       <option value="${cardType.id}">${cardType.name}</option>
    </c:forEach>
 </select>
 <select name="category" class="form-control">
    <c:forEach items="${cardCategories}" var="cardCategory">
       <option value="${cardCategory.id}">${cardCategory.name}</option>
    </c:forEach>
 </select>
<textarea type="text" name="description" class="form-control" rows="6"></textarea>
 <input type="submit" id="add-card-submit" value="Add card" class="btn btn-primary"/>

Here is Ajax function:

$(document).on('submit', '#add-card-form', function(e) {
    var frm = $('#add-card-form');
    e.preventDefault();

    var Form = this;
    var data = {};

    $.each(this, function(i, v){
        var input = $(v);
        data[input.attr("name")] = input.val();
        delete data["undefined"];
    });

    //temporary solution
    data["type"] = parseInt(data["type"]);
    data["category"] = parseInt(data["category"]);

    console.log(data);
    if(frm.valid()) {
        $.ajax({
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            type: frm.attr('method'),
            url: frm.attr('action'),
            data: JSON.stringify(data),
            success:  reloadBoard,
            error: function (callback) {
                console.log(callback);
            }
        });

        refreshForm(frm);
    }
});

And here is a controller action:

@RequestMapping(value="/add", method = RequestMethod.POST)
public @ResponseBody Card addCard(@RequestBody Integer type,
                                  @RequestBody Integer category,
                                  @RequestBody String description) {

    Card card = new Card();

    card.setType(cardTypeService.findById(type));
    card.setCategory(cardCategoryService.findById(category));
    card.setDescription(description);
    card.setOwner(1);

    cardService.saveCard(card);

    System.out.println("Card with id " + card.getId() + " added!");

    return card;
}

Variable data values:

Object {type: 1, category: 1, description: "New Card"}

When I try to send this form I always get error 400: http://localhost:8080/card/add 400 (Bad Request)

Can you tell me what is wrong with this code? I've ridden few posts, articles about sending data using Spring MVC + Ajax but no one helped.

EDIT:

I changed @RequestBody into three @RequestParams:

 @RequestMapping(value="/add", method = RequestMethod.POST)
public @ResponseBody Card addCard(@RequestParam("type") Integer type,
                                  @RequestParam("description") String description,
                                  @RequestParam("category") Integer category) {

I still get 400 error. Here is raw HTTP request:

POST /card/add HTTP/1.1 Host: localhost:8080 Connection: keep-alive Content-Length: 48 Cache-Control: no-cache Pragma: no-cache Origin: http://localhost:8080 X-Requested-With: XMLHttpRequest Content-Type: application/json; charset=UTF-8 Accept: application/json, text/javascript, */*; q=0.01 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 Referer: http://localhost:8080/ Accept-Encoding: gzip,deflate,sdch Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4 Cookie: JSESSIONID=ABAD895C419A9175EAB4D0833C543724

And data object:

category: 1
description: "New Card"
type: 1

Dmitry Zolotukhin is right when saying that the only reasonable thing is to have only one @RequestBody as you can consume the request only once, after that it becomes commited and all subsequent read attempts will fail.

What you should do is have your Card class as method argument annotated with @RequestBody , so

@RequestMapping(value="/add", method = RequestMethod.POST)
public @ResponseBody Card addCard(@RequestBody Card card) {
    card.setOwner(1);
    cardService.saveCard(card);
    System.out.println("Card with id " + card.getId() + " added!");
    return card;
}

The spring mvc framework will take care of the instantiation of the Card object and binding the request values to properties, by matching the keys from JSON body with properties. Note also that for this to work, the data you're sending must be a valid json, so make sure that to comply to that.

You can consider creating a simply data transfer object, eg CardDTO something like

public class CardDTO {
    private Integer category;
    private Integer type;
    private String descrption;

    public Integer getCategory() {
        return category;
    }

    public void setCategory(Integer category) {
        this.category = category;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public String getDescrption() {
        return descrption;
    }

    public void setDescrption(String descrption) {
        this.descrption = descrption;
    }
}

and than bind to it

@RequestMapping(value="/add", method = RequestMethod.POST)
public @ResponseBody Card addCard(@RequestBody CardDTO cardDTO) {

@RequestBody means that the contents of the HTTP request body will be mapped to the attribute. Since you can only have one request body, this will almost certainly fail.

You most likely need to specify the request param instead: @RequestParam("type") String type

If this doesn't help, could you provide the raw HTTP request data and the Spring MVC error stack trace from the web server's log/console?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM