Question

Let's say I've got a form for editing the properties of a Pony, and in my web application there are multiple places where you can choose to edit a Pony. For instance, in a list of Ponies there might be an "edit" link next to each Pony, and when the user is viewing a Pony, there might also be an "edit" link in that view.

When a user clicks "submit" after editing a Pony, I would like to return the user to the page that he or she was when clicking the "edit" link.

How do I write my controller to redirect the user back to where they started? Certainly I can do this by passing a parameter to the controller, but that seems a little goofy. Am I thinking about this all wrong or is that pretty much what I'll have to do?

Was it helpful?

Solution

One option, of course, would be to open the edit form in a new window, so all the user has to do is close it and they're back where they were.

There are a few places in my current application where I need to do something complicated, then pass the user to a form, and then have them return to the starting point. In those cases I store the starting point in the session before passing them off. That's probably overkill for what you're doing.

Other options: 1) you can store the "Referer" header and use that, but that may not be dependable; not all browsers set that header. 2) you could have javascript on the confirmation page after the form submission that calls "history.go(-2)".

OTHER TIPS

Here's how to do it boys (Note this is RESTful Spring 3 MVC syntax but it will work in older Spring controllers):

@RequestMapping(value = "/rate", method = RequestMethod.POST)
public String rateHandler(HttpServletRequest request) {
    //your controller code
    String referer = request.getHeader("Referer");
    return "redirect:"+ referer;
}

My answer is alike to Sam Brodkins´s (i recomended it also). But having in count that the "Referer" value may not be available i made this function to use it in my controllers

/**
* Returns the viewName to return for coming back to the sender url
*
* @param request Instance of {@link HttpServletRequest} or use an injected instance
* @return Optional with the view name. Recomended to use an alternativa url with
* {@link Optional#orElse(java.lang.Object)}
*/
protected Optional<String> getPreviousPageByRequest(HttpServletRequest request)
{
   return Optional.ofNullable(request.getHeader("Referer")).map(requestUrl -> "redirect:" + requestUrl);
}

So in your controller caller function you should return something like this:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody
String testRedirection(HttpServletRequest request)
{
      //Logic....
      //Returns to the sender url
      return getPreviousPageByRequest(request).orElse("/"); //else go to home page
}

Yes I think Jacob's idea for the form in a new window may be a good option. Or in a hidden div. Like a dojo dialog. http://dojocampus.org/explorer/#Dijit_Dialog_Basic

one other option would be to design your urls so they reveal the context of what you're doing, and by convention, would allow you to "know" where the start of an operation was.

For example, you could have urls like so

site/section1/pony/edit
site/section1/pony/delete

site/somewhere/else/entirely/pony/edit
site/somewhere/else/entirely/pony/delete

both those urls allow pony editing and deleting. To go back to the start for both of them, you'd simply go "up" 2 folders. This could be done via a javascript function that looks at the current url, and just goes up 2 folders, or you could figure it out on the server side 2, and do a redirect like that as well.

You can also keep track of the ModelAndView (or just the view) that have been last presented to the user with an interceptor. This example keeps track of only the last model and view, but you could use a list to navigate back more levels.

package com.sample;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LastModelAndViewInterceptor extends HandlerInterceptorAdapter {

    public static final String LAST_MODEL_VIEW_ATTRIBUTE = LastModelAndViewInterceptor.class.getName() + ".lastModelAndView";

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        request.getSession(true).setAttribute(LAST_MODEL_VIEW_ATTRIBUTE, modelAndView);
        super.postHandle(request, response, handler, modelAndView);
    }

}

With Spring XML configuration:

<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="interceptors">
        <bean class="com.sample.LastModelAndViewInterceptor"/>
    </property>
</bean>

And then use the following code to get back to that view in a controller:

ModelAndView mv = (ModelAndView)request.getSession().getAttribute(LastModelAndViewInterceptor.LAST_MODEL_VIEW_ATTRIBUTE);
return mv;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top