Можно ли использовать RedirectToAction() внутри пользовательского класса AuthorizeAttribute?

Используя ASP.Net MVC 2, можно ли использовать метод RedirectToAction() Controller внутри класса, основанного на классе AuthorizeAttribute?

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");
    }
}

Я ищу способ перенаправить пользователя на конкретный контроллер/действие, когда они не выполняют аутентификацию, а не возвращают их на страницу входа. Возможно ли иметь перенаправленный URL-адрес для этого контроллера/действия, а затем использовать RedirectResult()? Я пытаюсь избежать соблазна просто скопировать URL-адрес.

Ответы

Ответ 1

Вы можете/должны переопределять HandleUnauthorizedRequest вместо OnAuthorization. Здесь используется реализация по умолчанию:

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

Вы не можете использовать Controller.RedirectToAction, но вы можете вернуть новый RedirectToRouteResult.

Итак, вы можете сделать:

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

Ответ 2

Вы можете сделать что-то вроде этого:

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

Это так, как это делает инфраструктура, когда вы вызываете "RedirectToAction()" в своем контроллере.

Ответ 3

Если кто-то еще интересуется этим вопросом. Это можно решить более простым способом (по крайней мере с использованием MVC 3, не знаю о MVC 2):

Просто создайте небольшой закрытый контроллер в своем пользовательском атрибуте AuthorizeAttribute:

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

    }

Это можно легко использовать в методе HandleUnauthorizedRequest (см. ответ Craigs):

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