ASP.NET MVC 3 - Detect Whether Current Page Was Re

2019-04-12 03:12发布

问题:

In my C# .NET 4 MVC 3 application I have a delete controller for a set of CRUD pages which uses the Post Redirect Get pattern to redirect to an Index controller after a successful delete. I would like to render a button on the Index page only if this page was NOT redirected to by such an action. Is there a simple way to detect if the current page was redirected to (i.e. was reached as the result of a PRG redirect)?

After reading http://blog.simonlovely.com/archive/2008/11/26/post-redirect-get-pattern-in-mvc.aspx my current approach is to set this in my delete controller with TempData after the DeleteMyEntity method has succeeded:

try {
    MyService.DeleteMyEntity(MyViewModel.MyEntity);
    TempData["Redirected"] = true;
    args = new RouteValueDictionary(new { Foo = 1, Baa = 2 });
    return RedirectToAction("Index", args);
} catch (Exception e)
{
   //Logging etc. - redirect should never be reached on exception (and TempData item not set)
   throw(e);
}

then in my Index controller I check to see if this value exists and is true:

if (TempData["Redirected"] != null)
{
    //we can then do something useful with this
}

Another opportunity I see would be to add another item to args and check for this in the controller, but in this case I may as well just use TempData. Is there a way to do this using a HTTP Response code on the request without needing to pass this data through with TempData or a similar mechanism?

回答1:

I use TempData in a similar fashion - for instance, to show a status message (after redirecting to) my view when a record has been added / updated / deleted. This is the kind of simple, throw-away stuff that TempData is used for, so I say what you have is appropriate.

Personally I wouldn't mess with HTTP status codes unless I had an absolute need for it. And you could probably do something with the referrer http header, but again, that would be much messier and more complicated than just using TempData. You have a clean, simple solution that works, I say go with what you have.



回答2:

another route would be to set up a global actionfilter that "injects" that flag for you...

public class RedirectDetect: ActionFilterAttribute{
   public override void OnActionExecuted(ActionExecutedContext filterContext){
        if (filterContext.Result is RedirectToRouteResult ||
            filterContext.Result is RedirectResult)
        {
             TempData["Redirected"] = true;
             //or what ever other indicator you want to set
        }
   }
}

And then you can just call redirectToAction("Index") and then check in your receiving handler

sidenote: I challenge you to say RedirectDetect aloud and not smirk.



回答3:

I am not aware of any simpler mechanism and have been using TempData for quite some time to implement Post-Redirect-Get features. As far as I know, this is specifically one of the reasons for TempData's existence. I would continue using it.



回答4:

There is no way to tell the difference between requests as a result of a 3xx redirection or a straightforward user-initiated GET. The best way is to provide a querystring argument that is only appended by the redirection for the initial POST request, but there is nothing stopping the user from reloading the page with the same querystring.

Hmmm, or you could send a cookie with the redirection from the POST, then remove the cookie in the response of the subsequent GET, like so:

public ActionResult PostHandler(ViewModel model) {
    SetCookie("redirected", "true"); // psuedocode
    return Redirect("GetHandler2");
}

public ActionResult GetHandler2() {
    if( GetCookie("redirected") == "true" ) {
        // do something
    }
    DeleteCookie("redirected");
}