Redirect to referent after POST request

I have a web application on Play. A web application consists of several pages. Each page has a small flag that allows the user to change the language (locale) from German to English and vice versa.

I handle this with a referer redirect:

def referer(implicit request: Request[AnyContent]) = request.headers.get(REFERER).getOrElse(mainUrl) def locale(l: String) = Authenticated { user => implicit request => Redirect(referer).withCookies(Cookie(LANG, if (l == "de" || l == "en") l else "de")) } 

It is working fine. Well, at least for GET requests.

I have a specific page where the user must enter data on the form. Then this form is sent to the server. If errors are detected, the form displays again with error messages, as usual. Now, if the user wants to change the language (by clicking on the flag), the redirection to the referent does not work, because he is trying to use a GET request, and Play complains that there is no GET route for this method (which is true).

I solve this by caching the form and defining another method in which the form is taken from the cache:

 # User data is POSTed to the server POST /create/insert controllers.MyCreate.insert() # After a redirect the cached form is displayed again GET /create/insert controllers.MyCreate.insertGet() 

It works, but I don't like it. It seems abnormal to create another entry in the routes and another method to simply address this problem. I need to add this hack for every POST route in my application!

Is there a more elegant solution?

+1
redirect post scala
source share
1 answer

You can change it to something like this (untested):

 def changeLang(lang:String, returnUri:String) = Action { Redirect(returnUri) .withCookies(Cookie(LANG, if (lang == "de" || lang == "en") lang else "de")) } 

In your template, you should output a route for changing the Lang in the link, you can get uri with request

 @routes.Application.changeLang("en", request.uri).url 

I suggest you make request implicit in your action and define it as implicit in your template, so you don't need to pass it to each template.

 // in the controller def myUrl = Action { implicit request => Ok(views.html.myTemplate("something")) } // in the template @(title:String)(implicit request:play.api.mvc.RequestHeader) 

Edit

As for POST requests, for ordinary types (for these types of frameworks) there are POST requests for a simple control, and then redirected to another page. A regular thread is as follows:

  • The form is submitted to the handler.
  • A handler does something with form information.
  • The handler is redirected to the page

Example:

 // Hooked up to a GET route def edit(id:Long) = Action { // render the view with a form that displays the element with given id // if the flash scope contains validation information, use that in display } // Hooked up to a POST route def editHandler = Action { // validate the form // if validation succeeds // persist the object // redirect to edit // else // put the form information into the flash scope // put any validation messages into the flash scope // redirect to edit } 

If you do not want to use this stream, you still need to have both a GET and a POST route. The user can reload the page on the resulting page.

0
source share

All Articles