Boden
Boden

Reputation: 4167

Spring-MVC controller redirect to "previous" page?

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?

Upvotes: 31

Views: 85967

Answers (7)

Rajat Verma
Rajat Verma

Reputation: 2590

response.sendRedirect(request.getHeader("Referer"));

Upvotes: 0

EliuX
EliuX

Reputation: 12625

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
}

Upvotes: 5

Werner Altewischer
Werner Altewischer

Reputation: 10466

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;

Upvotes: 1

Brad Parks
Brad Parks

Reputation: 71961

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.

Upvotes: 1

Sam Brodkin
Sam Brodkin

Reputation: 767

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;
}

Upvotes: 59

Derek
Derek

Reputation: 760

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

Upvotes: 1

Jacob Mattison
Jacob Mattison

Reputation: 51052

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)".

Upvotes: 7

Related Questions