7

Is there a good way to restrict the access to an action, so you can only access it, if you were redirected from another action. For example:

    [HttpPost]
    public virtual ActionResult Create(MyViewModel vm)
    {            
        if (ModelState.IsValid)
        {
            // do some work

            return RedirectToAction("CreateSuccess");
        }
        else
        {
            return View(vm);
        }
    }


    public virtual ActionResult CreateSuccess()
    {
        // only allow execution if you were redirected from Action "Create" 
    }
Fabiano
  • 5,124
  • 6
  • 42
  • 69
  • If execution is only to be allowed from Create, wont a private method also work in this case. I can see the PGR pattern, but you can deviate. – Ahmad Oct 05 '10 at 18:43

4 Answers4

7

An easy way would be to store a flag in TempData in the first method and check that the flag exists in the method that is redirected to.
TempData is there to pass state information between action requests and will only last the duration of the request so you will not need to worry about clearing it down.

Andy Rose
  • 16,770
  • 7
  • 43
  • 49
  • Be careful some redirect methods mark TempData to be kept and persisted across requests. [Here](http://stackoverflow.com/a/3982640/808271) more details. Seems to be old, but still is the case as I found out today ;) – slawek Mar 03 '14 at 12:28
2

There is no way to know the "from" action unless you include parameters indicating such. The easiest way is to append a "SourceAction" or "FromAction" parameter and check it in the "destination" action.

Dave Swersky
  • 34,502
  • 9
  • 78
  • 118
1

The question is, why do you want to do that? Maybe there is a better solution for your primary problem.

Anyway, you can use the HttpContext.Current.Request.UrlReferrer Property to check the previous page Url.

goenning
  • 6,514
  • 1
  • 35
  • 42
  • 1
    The reason is that I want to display some information, that should only be visible for people who successfully (and therefore authorized) performed a previous action – Fabiano Oct 05 '10 at 14:25
  • 1
    Then I would do what Andy Rose did, but using Session insted of TempData. By using the Session your telling your application that the current user has performed a given action and he is able to execute that action. Or even put it on a Database if you want to use that information for longer than a Session. – goenning Oct 05 '10 at 14:31
  • Relying on the HTTP Referrer header is not ideal because it can be easily spoofed and some proxies and firewalls remove this header. – Llyle Dec 10 '11 at 03:11
1

First solution

You could just do this:

[HttpPost]
public virtual ActionResult Create(MyViewModel vm)
{            
    if (ModelState.IsValid)
    {
        // do some work
        return this.CreateSuccess();
    }
    else
    {
        return View(vm);
    }
}

[NonAction]
public virtual ActionResult CreateSuccess()
{
    // do what's needed 
}

This last method will only be executed from other action methods. But it can't be executed per se.

Second solution

You could solve this by creating a custom action method selector attribute as well if you know you can reuse this. You could write a custom action method selector attribute that checks request referrer and uses appropriate method.

Read about custom action selector attributes.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404