2017-02-19 35 views
0

POST ИНГ JSON с JavaScript на сервере в Play Framework:Play Framework 2.5 АЯКС параметр JSON маршрут асинхронной MongoDB

var myJson = {"name": "joe", "age":20}; 
var obj = JSON.parse(myJson); 

$.ajax(jsRoutes.controllers.MyController.create(obj)); 

Теперь у меня есть Java-маршрутизатор настроен отлично. Если я получаю obj как строку, я могу просто распечатать ее на консоли.

routes.conf: 

POST /person/add  controllers.MyController.createFromAjax(ajax: String) 

НО, я хочу написать JSON в MongoDB используя обещание Async, который Активатор дает ошибку во время компиляции:

scala.concurrent.Future[play.api.mvc.Result][error] cannot be applied to (String) 

У меня есть другие маршруты, которые не принимают никаких параметров, которые получают JSON с помощью почтальона и записать его в MongoDB просто отлично

routes.conf 

POST /heartrates/bulk   controllers.HRController.createFromJson 

Если я опустить параметр на маршрут, который принимает JSON из Ajax вместо того, чтобы использовать Почтальон я получаю ошибку HTTP 400 в братан Wser.

POST http://localhost:9000/person/add 400 (Bad Request) 

SO, мой вопрос, Ajax нуждается в параметре, но String не будет работать. Документация по игре говорит, что json всегда принимается как строка. Что я здесь делаю неправильно?

Scala Controller Код взят из Lightbend семян Play.Reactive.MongoDB:

def createBulkFromAjax = Action.async(parse.json) { request => 

val documents = for { 
    heartRate  <- request.body.asOpt[JsArray].toStream 
    maybeHeartRate <- heartRate.value 
    validHeartRate <- maybeHeartRate.transform(transformer).asOpt.toList 
} yield validHeartRate 

for { 
    heartRate <- hrFuture 
    multiResult <- heartRate.bulkInsert(documents = documents, ordered = true) 
} yield { 
    Logger.debug(s"Successfully inserted with multiResult: $multiResult") 
    Created(s"Created ${multiResult.n} heartRate") 
} 
} 
+0

Можете ли вы показать нам свой код контроллера? – millhouse

+0

Добавлен код контроллера Scala. –

ответ

0

Я думаю, вы получаете перепутаны между параметрами, которые Вы передаете на ваш Action как часть jsRoutes вызова, а также параметров, получать переданные конечные точки (т. е. строку запроса, параметры запроса и т. д.).

Play вернет 400 Bad Request, если вы объявили необязательный параметр (например, вы сделали это с ajax: String), и тогда вы не отправляете его в свой запрос.

Хотя концептуально вы являются проходя obj к вашему действию, это не в качестве параметра запроса - вы заявили, что ваша конечная точка ожидает POST HTTP - поэтому JSON должен быть в теле запроса HTTP. Обратите внимание, что другие конечные точки не принимают никаких параметров запроса.

Так шаг 1 это исправить файл routes (я переименовал свой метод, чтобы соответствовать любой другой имеющийся работать один):

POST /person/add  controllers.MyController.createFromJson 

Если вы посмотрите на Play documentation for the Javascript reverse router, вы увидите, что вам нужно установить type (иначе HTTP-метод), если вы делаете что-то другое, кроме GET. Так, шаг 2, вот что ваш Javascript должен выглядеть, чтобы достичь POST:

var myJson = {"name": "joe", "age":20}; 
var obj = JSON.stringify(myJson); 

var r = controllers.MyController.createFromJson; 
$.ajax({url: r.url, type: r.type, data: obj }); 

После этих изменений вы должны быть хорошо; ваш код контроллера выглядит нормально. Если вы еще получите 400 Bad Request ответы, убедитесь, что jQuery правильно устанавливает ваш заголовок Content-Type - вам может понадобиться use the contentType option in the jQuery $.ajax call.

Edit после получения еще 400 ошибок:

Я только заметил, что вы использовали JSON.parse в вашем Javascript - as per this answer вы должны использовать JSON.stringify для преобразования объекта в нечто JQuery может отправить - в противном случае это может попробуйте URLEncode данные и/или отправьте поля в качестве параметров запроса.

Другая вещь, на которую стоит обратить внимание, заключается в том, действительно ли отправляемый вами JSON согласен с тем, что вы пытаетесь разобрать. Я не уверен, если вы ввели упрощенную версию на этот вопрос, но похоже, что вы пытаетесь разобрать:

{"name": "joe", "age":20} 

Использование:

request.body.asOpt[JsArray] 

который будет всегда результат в a None - вы не дали массив.

+0

Я установил jsrouter согласно Play документации, поэтому единственный маршрут, на который javascript не жалуется, это: var r = jsRoutes.controllers.MyController.createFromJson(); $ .ajax ({url: r.url, contentType: "application/json", type: r.type, data: JsonObj}); Я добавил contentType param в ajax, как указано выше, но все еще получаю ошибку 400 jsrouter, похоже, работает отлично: POST http: // localhost: 9000/person/add 400 (Bad Request) Любая дополнительная помощь оценивается. Благодарю. –

+0

Эй, Эй, это работает. Я упростил свой код для этого вопроса, но, оказывается, моя проблема была дублированным маршрутом в route.conf с того момента, когда я передавал json в качестве параметра. Удалил маршрут, и он работает с Json.parse или без него, потому что я был жестко закодирован в квадратных скобках. Я не знал о шнуровке. Спасибо за помощь @millhouse. Я уверен, у меня будет больше вопросов. –

+0

исправление, вы были правы о json.parse. Я удалил его. оно работает. –

0

Ответ на JavaScript Ajax маршруты в Play Framework 2.5 для ReativeMongo:

routes.conf:

GET  /javascriptRoutes  controllers.HRController.javascriptRoutes 

HRController:

def javascriptRoutes = Action { implicit request => 
Ok(
    JavaScriptReverseRouter("jsRoutes")(
    routes.javascript.HRController.createBulkFromAjax 
) 
).as("text/javascript") 

}

routes.conf:

POST /heartrates/add  controllers.HRController.createBulkFromAjax 

main.scala.html:

<script type="text/javascript" src="@routes.HRController.javascriptRoutes"></script> 

JavaScript:

var r = jsRoutes.controllers.HRController.createBulkFromAjax(); 
$.ajax({url: r.url, type: r.type, contentType: "application/json", data: JsonString }); 

HRController:

def createBulkFromAjax = Action.async(parse.json) { request => 
//Transformation silent in case of failures. 
val documents = for { 
    heartRate  <- request.body.asOpt[JsArray].toStream 
    maybeHeartRate <- heartRate.value 
    validHeartRate <- maybeHeartRate.transform(transformer).asOpt.toList 
} yield validHeartRate 

for { 
    heartRate <- hrFuture 
    multiResult <- heartRate.bulkInsert(documents = documents, ordered = true) 
} yield { 
    Logger.debug(s"Successfully inserted with multiResult: $multiResult") 
    Created(s"Created ${multiResult.n} heartRate") 
} 
} 

HRController.createBulkFromAjax был построен из примера Lightbend активатор щ семян называется игра .ReactiveMogno