简体   繁体   中英

Spring Web Mvc jQuery AJAX call with post not bidinding from with @ModelAttribute

I am trying to send an AJAX call with jquery to a spring web mvc application. I have a modal which contains a form:

<div id="editTileModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true" style="display: none;">
<div class="modal-dialog modal-lg">
    <form id="frmEditTileModal" modelAttribute="editTile" class="floating-labels " action="/DESSOApplicationPortalAdmin/rest/tile/002" method="POST">
    <div class="modal-content">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h4 class="modal-title" id="myLargeModalLabel">Edit Tile</h4>
        </div>
        <div class="modal-body">

            <div class="row">

                    <div class="col-md-6" >


                        <div class="form-group m-b-40 margin-top-20">
                            <input type="text" class="form-control" id="editTileId" name="id" required><span class="highlight"></span> <span class="bar"></span>
                            <label for="editTileId">Id</label>
                        </div>
                        <div class="form-group m-b-40">
                            <input type="text" class="form-control" id="editTileDescription" name="description" required><span class="highlight"></span> <span class="bar"></span>
                            <label for="editTileDescription">Description</label>
                        </div>
                        <div class="form-group m-b-40">
                            <input type="text" class="form-control" id="editTileRole" name="role" required><span class="highlight"></span> <span class="bar"></span>
                            <label for="editTileRole">Role</label>
                        </div>
                    </div>
                    <div class="col-md-6" >
                        <div class="form-group m-b-40 margin-top-20">
                            <input type="text" class="form-control" id="editTileTarget" name="target" required><span class="highlight"></span> <span class="bar"></span>
                            <label for="editTileTarget">Target</label>
                        </div>
                        <div class="form-group m-b-40">
                            <input type="text" class="form-control" id="editTileIndex" name="index" required><span class="highlight"></span> <span class="bar"></span>
                            <label for="editTileIndex">Index</label>
                        </div>
                        <div class="form-group m-b-40">
                            <input type="text" class="form-control" id="editTileTileimagename" name="tileImageName" required><span class="highlight"></span> <span class="bar"></span>
                            <label for="editTileTileimagename">Tile Image Name</label>
                        </div>
                    </div>
                    <div class="col-md-12">
                        <div class="form-group m-b-40">
                            <input type="text" class="form-control" id="editTileUrl" name="url" required><span class="highlight"></span> <span class="bar"></span>
                            <label for="editTileUrl">Url</label>
                        </div>
                    </div>

                    <div class="col-md-12">                           
                        <div class="form-group m-b-40 form-check">
                            <label class="custom-control custom-checkbox">
                                <input type="checkbox" class="custom-control-input">
                                <span class="custom-control-indicator"></span>
                                <span class="custom-control-description">Disable Tile</span>
                            </label>
                        </div>
                    </div>

                    <div class="row>">
                        <div class="col-sm-6 col-md-6 col-xs-12">
                            <div class="white-box">
                                <h3 class="box-title">Tile Image Normal</h3>
                                <label for="img-tile-normal">You can add a default value</label>
                                <input type="file" id="img-tile-normal" class="dropify" data-default-file="resources/vendor/plugins/bower_components/dropify/src/images/test-image-1.jpg" />
                            </div>
                        </div>
                        <div class="col-sm-6 col-md-6 col-xs-12">
                            <div class="white-box">
                                <h3 class="box-title">Tile Image on Hover</h3>
                                <label for="img-tile-on-hover">You can add a default value</label>
                                <input type="file" id="img-tile-on-hover" class="dropify" data-default-file="resources/vendor/plugins/bower_components/dropify/src/images/test-image-1.jpg" />
                            </div>
                        </div>
                    </div>



            </div>
        </div>

        <div class="modal-footer">
            <button type="button" class="btn btn-default waves-effect" data-dismiss="modal">Close</button>
            <button id="btnSaveEditTile" type="submit" class="btn btn-danger waves-effect waves-light">Save changes</button>
        </div>
    </div>
    </form> 
    <!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->

This is the jQuery

       $('#frmEditTileModal').submit(function (e) {
        e.preventDefault();
        alert("save edit start!");

        var editSuccesFunc = function () {
            alert('Success Edit!');
        };
        var editErrorFunc = function () {
            alert('Error Edit!');
        };

        var tileId = $('#editTileId').val();
        alert("data to send: " + $('#editTileId').val());

        var formData = new FormData();
        formData.append("id", $('#editTileId').val());
        formData.append("description", $('#editTileDescription').val());
        formData.append("role", $('#editTileRole').val());

        $.ajax({
            type: "POST",
            url: "/DESSOApplicationPortalAdmin/rest/tile/" + tileId,
            data: $('#frmEditTileModal').serialize(),
            contentType: "application/json",
            dataType: "json",
            success: editSuccesFunc,
            error: editErrorFunc
        });
    });

and this is the java controller:

    @RestController
    @RequestMapping(value = "rest/tile")
public class TileRestController {

    @Autowired
     TileService tileService;

    @RequestMapping(value = "/{tileId}", method = RequestMethod.GET)
       public Tile getProductById(@PathVariable(value = "tileId") String tileId) {
        System.out.println("------------->" + this.getClass().getSimpleName() + ": getProductById called. Searching for Tile Id " + tileId);
        return tileService.getTileById(tileId);
    }

    @RequestMapping(value = "/{tileId}", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
    @ResponseBody
    public  Tile update( @ModelAttribute("editTile") Tile tile, @PathVariable(value = "tileId") String tileId) {
        Tile updatedTile = new Tile();
        //updatedTile.setId("099");
        //updatedTile.setDescription("ExampleTile");

        System.out.println("------------->" + this.getClass().getSimpleName() + " update method: print object fields: "+tile.toString());
        return updatedTile;
       //return tileService.updateTile(tile);

    }
}

When I try a doing a normal submit (no ajax or jquery) the controller correctly reads the field to the object.

However when, I try doing the same as an ajax call, it correctly sends the data but the controllers does not map it to an object via modelAttribute("editTile"). Here is a print of the class:

------------->TileRestController update method: print object fields: Tile{ tileImageName=null, description=null, role=null, url=null, target=null, index=0, id=null, disabled=false}

Am I missing something?

EDIT: I tried a suggestion made in the answers, but it did not seem to work. Here is what I did:

I change the code of the update method in order to use the @RequestBody annotation

@RequestMapping(value = "/{tileId}", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
public  Tile update( @RequestBody Tile tile, @PathVariable(value = "tileId") String tileId) {
    Tile updatedTile = new Tile();
    //updatedTile.setId("099");
    //updatedTile.setDescription("ExampleTile");

    System.out.println("------------->" + this.getClass().getSimpleName() + " update method: print object fields: "+tile.toString());
    return updatedTile;
   //return tileService.updateTile(tile);

}

plus, I changed my content type as well for the ajax call:

$.ajax({
            type: "POST",
            url: "/DESSOApplicationPortalAdmin/rest/tile/" + tileId,
            data: $('#frmEditTileModal').serialize(),
            contentType: "application/www-form-url-encoded",
            dataType: "json",
            success: editSuccesFunc,
            error: editErrorFunc
        });

however, now I get an ajax error, it it does not even make the call: 在此处输入图片说明

在此处输入图片说明

You seem to be Posting a JSON (content-type: application/json) from ajax.

Try using @RequestBody instead of @ModelAttribute for the Tile.

A FORM post normally gets post'ed as content-type: application/www-form-url-encoded.

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