10

I am using Razor on ASP.NET MVC with C#.

I am calling an external web page to process a credit card and it returns to me. I then display a receipt.

I'd like to prevent them from going back to the previous screen.

I do not have an underlying cs page, like asp since these are .cshtml files, to grab the event.

This receipt page is a View so I cannot put JavaScript in the header since it would affect every page using it.

Anyone know how I prevent the back button in this circumstance?

tereško
  • 58,060
  • 25
  • 98
  • 150
ErocM
  • 4,505
  • 24
  • 94
  • 161
  • This will be a javascript piece of code to do this. C# won't have anything to do with it, as the C# is all server side. I'm sure you can search Stackoverflow for the answer to this, though. [Edit: I did the search for you.](http://stackoverflow.com/search?q=prevent+back+button+browser) – Gromer Oct 19 '12 at 16:13
  • Also, if you use sections in your Razor files, you can inject javascript in the page from a specific partial view Razor file. Check this blog out for more info: http://weblogs.asp.net/scottgu/archive/2010/12/30/asp-net-mvc-3-layouts-and-sections-with-razor.aspx – Gromer Oct 19 '12 at 16:17
  • Can't scripting be disabled on the browser which would ignore this? – ErocM Oct 19 '12 at 16:19
  • Yup. You still have to write code to make sure people don't goof stuff up, no matter what. Or just prevent the users from using the site if js is disabled. That decision depends on what the site does, your user base, etc..., though. – Gromer Oct 19 '12 at 16:20

6 Answers6

14

One possibility is to exclude the page you don't want to get back to from caching on the client. This could be done by setting the proper response headers. Here's an example with a [NoCache] custom action filter which you could use to decorate the corresponding controller action.

Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
7

Firstly, if the previous page posted data to the server, best to Redirect(...) to another action after the successful processing, to avoid the data being resubmitted on "Refresh".

Then also set the page to expire, so the back button doesn't work:

https://stackoverflow.com/a/5352953/864763

Community
  • 1
  • 1
Paul Grimshaw
  • 19,894
  • 6
  • 40
  • 59
4

You're asking the wrong question. Don't try to disable "back" on the client. This will be doomed to fail; you may be able to make it harder, but you'll never win that fight. Instead you should re-write the particular page that you have such that it will only ever process the credit card once. You should (on the server) "remember" that you've processed the credit card so that if the user goes back to the page to resubmit it you can just give them an error message saying "you have already submitted this information, you cannot submit this request twice".

Now, there are several ways of accomplishing this general goal, and some are better than others, but that's the goal you need to strive towards.

One way to do this is to go to every page that will redirect the user to this credit card form; just before submitting the request add something to that user's session (i.e. "pendingCreditCardSubmission" = true) Once they submit that request you then check for that session variable. If it's true, submit the request and set it to false, if it's false or not there then send an error message to the user.

Servy
  • 202,030
  • 26
  • 332
  • 449
2

This is how we did it:

public class NoBackFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        filterContext.HttpContext.Response.ExpiresAbsolute = DateTime.Now;
        filterContext.HttpContext.Response.Expires = 0;
        filterContext.HttpContext.Response.CacheControl = "no-cache";
        filterContext.HttpContext.Response.Buffer = true;
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
        filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow);
        filterContext.HttpContext.Response.Cache.SetNoStore();
        filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        if (!filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.HttpContext.Request.HttpMethod != "POST" && !filterContext.Controller.ControllerContext.IsChildAction)
        {
            var after = filterContext.HttpContext.Request.RawUrl;
            var session = GetSession(filterContext);
            if (session["Current"] != null)
            {


                if (session["Before"] != null && session["Before"].ToString() == after)
                    filterContext.HttpContext.Response.Redirect(session["Current"].ToString());
                else
                {
                    session["Before"] = session["Current"];
                    session["Current"] = after;
                }
            }
            else
            {
                session["Current"] = after;
            }
        }
        base.OnActionExecuting(filterContext);

    }

    private HttpSessionStateBase GetSession(ActionExecutingContext context)
    {
        return context.HttpContext.Session;
    }

}

After this you can implement it either in the general scope or in the controller scope.

1

It has been long since this was asked, but my fix was adding the [NoCache] above the WebPageController class.

 [NoCache]
public class WebPageController : Controller
{
    public JsonResult JsonError(Exception exception)
    {
        if (exception == null) throw new ArgumentNullException("exception");

        Response.StatusCode = 500;

        return new JsonResult
        {
            JsonRequestBehavior = JsonRequestBehavior.AllowGet,
            Data = new
            {
                error = true,
                success = false,
                message = exception.Message,
                detail = exception.ToString()
            }
        };
    }
Eduard Braun
  • 370
  • 3
  • 5
0

in MVC aspnet framework, you may choose to RedirectToActionPermanent

Which then it tells the browser 301 response code.

https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.redirecttoactionpermanent?view=aspnetcore-5.0

Jay
  • 1,869
  • 3
  • 25
  • 44