Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

RedirectToAction in Filter Attributes

Thankfully, ASP.NET MVC now has filters, seemingly called thus because that’s what they are called in Monorail whereas "interceptors" would probably be a more appropriate name.

So I did what I imagine ninety percent of people are going to use the thing for: created a filter to authenticate a controller/action. You know the one. If you aren’t authenticated then redirect to the login page. It’s a problem that apparently still hasn’t been solved to everyone’s satisfaction given the number of solutions out there.

I turn to my natural resource, CodeCampServer, and check out their solution (off-topic code has been removed):

    public override void OnActionExecuting(FilterExecutingContext filterContext)
    {
        if(!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Cancel = true;                                           
            //no way to access RedirectToAction() or Url.Action() here....
            filterContext.HttpContext.Response.Redirect("~/login?redirectUrl=" + HttpUtility.UrlEncode(filterContext.HttpContext.Request.Url.PathAndQuery));
        }
    }

Alas, my crest has fallen. No way to access RedirectToAction or Url.Action from within a filter attribute. They are protected or internal, I don’t care which because neither will help me.

Side note

I’m surprised more people haven’t mentioned one of the major reasons I see for not redirecting to hard-coded URLs. I’m developing on Windows XP and *not* using Cassini. Which means I’ve had to use .mvc in my routes as per the handy little comment in the default Global.asax.cs. But when I deploy to an IIS 7.0-ish environment, it’s nice to know I can change the route table in one place and not have to worry about hard-coded URLs anywhere.

So I’m not liking that little hard-coding in there. But here’s where it’s nice to have the actual source code for MVC (and on another side note: I’d reckon the CodePlex project should be named in such a way that it actually shows up when you search for "MVC" on that site, as opposed to the generic name it has now). What I want is what happens when I do a RedirectToAction.

Taking a look through the RedirectToAction code, I came up with something I’m not going to show you. It worked like a charm but after I wrote it, I found an even better method from SteveSanderson which is a slight variation on the theme:

    public override void OnActionExecuting(FilterExecutingContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Cancel = true;
            var requestContext = new RequestContext( filterContext.HttpContext, filterContext.RouteData );
            var values = new RouteValueDictionary(new { Action = "Index", Controller = "Login" });
            var vpd = RouteTable.Routes.GetVirtualPath(requestContext, values);
            var target = vpd.VirtualPath;
            var url = HttpUtility.UrlEncode(filterContext.HttpContext.Request.Url.PathAndQuery);
            filterContext.HttpContext.Response.Redirect(target + "?redirectUrl=" + url);

        }
    }

Please note the relative nature of the term "even better". This is by no means ideal but my NOR (Naive Optimism Radar) tells me that this will get better.

Final side note: Yes, there’s nothing stopping me from using FormsAuthentication.LoginUrl instead of a controller action but c’mon, it’s so 1.1.

Kyle the Nouveau

This entry was posted in ASP.NET MVC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Kyle Baley

    @Liam

    Serves me right for leaving my comfort zone by trying to be snarky. You’re probably right. I know little about Ruby and/or/on Rails save for the hello world walkthrough.

  • http://www.eclipsewebsolutions.com.au Liam McLennan

    Its interesting that you said, “ASP.NET MVC now has filters, seemingly called thus because that’s what they are called in Monorail”. I would have thought the terminology, and the whole idea, comes from Ruby on Rails.

  • http://devlicio.us/blogs/derik_whittaker/default.aspx Derik Whittaker

    if 90% are going to use filters for authentication, what percentage are going to use it for logging/trace actions??? I suggest at least 50%. And a good number of people will ONLY use filters for ONLY logging/tracing or authentication.

    What really sucks is right now with drop 2, there is no easy way to test that the filter gets called via a unit tests. If I am wrong and someone figured out an easy way, please show me.

    Derik