Manu Chadha
Manu Chadha

Reputation: 16723

I am sending Ok but the browser is showing bad request

I am sending JSON to Play server from HTML page. but the server code is behaving in a strange way. Using debugger, I can see that the server first sends bad request response, then it processes my controller message and responds Ok.

In image 1, I send a request, the image has snapshot of JSON and I immediately get bad request response which is shown in image3. In image 2, the controller code gets executed (I assume after the server has sent bad request) and the server sends another 200 OK. The content type I am using in JQuery is text/json. If I use application/json, I get only bad request message and the controller code doesnt get executed at all

I suspect the problem is in Json.

@(form:Form[User2])

<!DOCTYPE html>
<html lang="en" xmlns:font-variant="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-COMPATIBLE" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>HTML Test</title>
    <link rel="stylesheet" type="text/css" href="@routes.Assets.at("stylesheets/bootstrap.min.css")">

    <!--link rel="stylesheet" href="stylesheets/bootstrap-theme.min.css"-->
    <style type="text/css">

        html, body {
          height:100%;
          margin:0;padding:0
        }

        .center-form {
          width:100%;
          margin:auto;
          position:relative;
          top:50%;
          transform: translateY(-50%)
}


</style>

    <script src="@routes.Assets.at("javascripts/jquery-3.1.1.min.js")"></script>
    <script src="@routes.Assets.at("javascripts/bootstrap.min.js")"></script>


</head>
<body>

<div class="container center-form" >

    <!-- for medium and large screens,
    First row of Bootstrap grid contains logo. Total 3 columns (12/4). Logo in middle column-->

    <div class="row" >
        <!--empty column-->
        <div class="col-md-4 col-lg-4" ></div>

        <!--logo column-->
        <!--div class="col-md-4 col-lg-4" >
            <div>
                <img src="@routes.Assets.at("images/SalesWorkspaceLogo303x64.png")" alt="SalesWorkspace Logo" height="64" width="303">
            </div>
        </div-->
        <!--empty column-->
        <div class="col-md-4 col-lg-4"></div>
        </div>

    <!-- for medium and large screens,
    Second row of Bootstrap grid contains the form for username and password. Total 3 columns (12/4). -->
        <div class="row" >
            <!--empty column-->
            <div class="col-md-4 col-lg-4"></div>

            <!--form-->
            <div class="col-md-4 col-lg-4">

            <form id="registration-form" action="/newreg" method="post">
                    <div class="form-group">
                        <label for="first-name">First Name</label>
                        <input type="text" class="form-control" id="first-name" name="first-name" value="@form("name").value" required>
                    </div>

                    <div class="form-group">
                        <label for="last-name">Last Name</label>
                        <input type="text" class="form-control" id="last-name" name="last-name" value="@form("name").value" required>
                    </div>

                    <div class="form-group">
                        <label for="email">Email</label>
                        <input type="email" class="form-control" id="email" name="email" value="@form("email").value" required>
                    </div>
                    <div class="form-group">
                        <label for="password">Password</label>
                        <input type="password" class="form-control" id="password" name="password" required>
                    </div>
                    <div class="form-group">
                        <label for="confirm-password">Confirm password</label>
                        <input type="password" class="form-control" id="confirm-password" required>
                    </div>

                    <div class="form-group">
                        <label for="street-name">Street Name</label>
                        <input type="text" class="form-control" id="street-name" name="street-name" required>
                    </div>

                    <div class="form-group">
                        <label for="country">Country</label>
                        <input type="text" class="form-control" id="country" name="country" required>
                    </div>

                    <button type="submit" class="btn btn-primary">Sign Up</button>
                </form>
            </div>
            <!--empty column-->
            <div class="col-md-4 col-lg-4"></div>
        </div>
</div>
<script src="@routes.Assets.at("javascripts/myScripts.js")"></script>
</body>
</html>

Controller

 def registrationRequest = Action (parse.json){ request =>
    (request.body \ "first-name").asOpt[String].map {name =>
          Ok("hello " + name)
    }.getOrElse{
      BadRequest("bad request")
    }
  }
}

myScripts.js

function objectifyForm(formArray) {//serialize data function

  returnArray = {};
  for (var i = 0; i < formArray.length; i++){
    returnArray[formArray[i]['name']] = formArray[i]['value'];
  }
  return returnArray;
}

$(document).ready(function(){
    // click on form submit
    $('#registration-form').on('submit',function(e){
    var details = JSON.stringify(objectifyForm($(this).serializeArray()));
    console.log(details)
        // send ajax
        $.ajax({
            url: '/newreg', // url where to submit the request
            type : "POST", // type of action POST || GET
            datatype : "json", // data type
            /* this doesn't work*/
            //contentType: "application/json; charset=utf-8",
            /*this does*/
            contentType: "text/json; charset=utf-8",
            data : details,
            success : function(result) {
                // you can see the result from the console
                // tab of the developer tools
                console.log(result);
            },
            error: function(xhr, resp, text) {
                console.log(xhr, resp, text);
            }
        })
    });
});

enter image description here

enter image description here

enter image description here

Upvotes: 1

Views: 90

Answers (1)

Andriy Kuba
Andriy Kuba

Reputation: 8263

You forget to cancel the original submit event, so you send form twice. One time as trivial HTML form, so play sends a bad request back. Another time by javascript as JSON, so play process it and sends back 200.

Just add one string to your JS function.

From :

$('#registration-form').on('submit',function(e){

To:

$('#registration-form').on('submit',function(e){
    e.preventDefault();  //prevent form from default submitting

Upvotes: 1

Related Questions