Is it possible to use RedirectToAction() inside a custom AuthorizeAttribute class?

asp.net Mvc

asp.net Mvc Problem Overview


Using ASP.Net MVC 2, is there any way to use the RedirectToAction() method of the Controller class inside a class that is based on the AuthorizeAttribute class?

public class CustomAttribute : AuthorizeAttribute {
    protected override bool AuthorizeCore(HttpContextBase context) {
        // Custom authentication goes here
        return false;
    }

    public override void OnAuthorization(AuthorizationContext context) {
        base.OnAuthorization(context);
    
        // This would be my ideal result
        context.Result = RedirectToAction("Action", "Controller");
    }
}

I'm looking for a way to re-direct the user to a specific controller / action when they fail the authentication instead of returning them to the login page. Is it possible to have the re-direct URL generated for that controller / action and then use RedirectResult()? I'm trying to avoid the temptation to just hard-code the URL.

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

You can/should override HandleUnauthorizedRequest instead of OnAuthorization. Here's the default implementation:

    protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
        // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
        filterContext.Result = new HttpUnauthorizedResult();
    }

You can't use Controller.RedirectToAction, but you can return a new RedirectToRouteResult.

So you can do:

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
        // Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
        filterContext.Result = new RedirectToRouteResult(
                                   new RouteValueDictionary 
                                   {
                                       { "action", "ActionName" },
                                       { "controller", "ControllerName" }
                                   });
    }

Solution 2 - asp.net Mvc

You can do something like this:

var routeValues = new RouteValueDictionary();
routeValues["controller"] = "ControllerName";
routeValues["action"] = "ActionName";
//Other route values if needed.
context.Result = new RedirectToRouteResult(routeValues);

This is the way the framework does it when you call "RedirectToAction()" in your controller.

Solution 3 - asp.net Mvc

In case anyone else is interested in this question. This can be solved in a simpler way (at least using MVC 3, don't know about MVC 2):

Just create a small private controller in your custom AuthorizeAttribute:

    private class RedirectController : Controller
    {
        public ActionResult RedirectWhereever()
        {
            return RedirectToAction("Action", "Controller");
        }

    }

This can easily be used in your HandleUnauthorizedRequest method (see Craigs answer):

filterContext.Result = (new RedirectController()).RedirectWhereever();

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionLance McNearneyView Question on Stackoverflow
Solution 1 - asp.net MvcCraig StuntzView Answer on Stackoverflow
Solution 2 - asp.net MvcMattias JakobssonView Answer on Stackoverflow
Solution 3 - asp.net MvcPetter LundanesView Answer on Stackoverflow