MVC Recipies: On Page Action Return to the previous page

Whenever you need a page to return to the previous page when you get an form submit or some other action, this can be used:

Have a base controller that is inherited by all your controllers. That is always a good idea – you can easily add things that work site-wide.
In you base controller have a OnActionExecuting overriden – here we are going to store the previous page.
Something like this:

public abstract partial class MyController : Controller
{

public ActionResult RedirectToPrevious(String defaultAction, String defaultController)
{
  if (Session == null || Session["PrevUrl"] == null)
  {
      return RedirectToAction(defaultAction, defaultController);
  }

  String url = ((Uri)Session["PrevUrl"]).PathAndQuery;

  if (Request.Url != null && Request.Url.PathAndQuery != url)
  {
      return Redirect(url);
  }

  return RedirectToAction(defaultAction, defaultController);
}


protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var httpContext = filterContext.HttpContext;

    if (httpContext.Request.RequestType == "GET"
        && !httpContext.Request.IsAjaxRequest()
        && filterContext.IsChildAction == false)    // do no overwrite if we do child action.
    {
        // stop overwriting previous page if we just reload the current page.
        if (Session["CurUrl"] != null 
            && ((Uri)Session["CurUrl"]).Equals(httpContext.Request.Url) ) 
            return;

        Session["PrevUrl"] = Session["CurUrl"] ?? httpContext.Request.Url;
        Session["CurUrl"] = httpContext.Request.Url;
    }
}
}

Now, as I figured, it is not the best idea for redirecting everything by default. For validation purposes you would like not to redirect

Then you can reference Session[“PrevUrl”] in controllers, but there is a better way of doing it – create attribute!

public class RedirectToPreviousPageAttribute : ActionFilterAttribute
{
///

/// Place [RedirectToPreviousPage] attribute on Controller action
/// and when you do submit of form, this functionality will kick in.
/// We check if Session has Previous URL set and force to redirect
/// to whatever it says.
/// If no Session variable is set, just do what it is supposed to do in the first place.
///

/// public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var httpContext = filterContext.HttpContext;

    if (httpContext.Session == null || httpContext.Session["PrevUrl"] == null)
    {
        base.OnResultExecuted(filterContext);
        return;
    }

    String url = ((Uri)httpContext.Session["PrevUrl"]).PathAndQuery;

    if (httpContext.Request.Url != null && httpContext.Request.Url.PathAndQuery != url)
    {
        httpContext.Response.Redirect(url);
    }


    base.OnResultExecuted(filterContext);

}

}

And now, wherever you are put this attribute on a controller action (or entire controller), it will redirect to the previous page:

[HttpPost]
public virtual ActionResult Edit(Model model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    _repository.InsertOrUpdate(model);
    _repository.Save();

    return RedirectToPrevious("Index", "Controller");
}

VoilĂ ! Good to go!