Як змусити фільтр перенаправити на іншу дію?


77

RedirectToActionзахищений, і ми можемо використовувати його лише всередині дій. Але якщо я хочу перенаправити у фільтрі?

public class IsGuestAttribute: ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!Ctx.User.IsGuest) 
            filterContext.Result = (filterContext.Controller as Controller)
                .RedirectToAction("Index", "Home");
    }
}

Відповіді:


104

RedirectToActionє лише допоміжним методом для побудови a RedirectToRouteResult(), тому, що ви робите, це просто створити нову RedirectToRouteResult()передачу разом RouteValueDictionary()зі значеннями для вашої дії.

Повний зразок на основі коду @Domenic у коментарі нижче:

public class IsGuestAttribute: ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!Ctx.User.IsGuest) 
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary 
                { 
                    { "controller", "Home" }, 
                    { "action", "Index" } 
                });
        }
    }
}

1
Ви також можете помістити цей код у OnExceptionметод, якщо ви встановилиfilterContext.ExceptionHandled = true;
demoncodemonkey

88

Ось приклад коду:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{

    if (!Ctx.User.IsGuest)
    {
        RouteValueDictionary redirectTargetDictionary = new RouteValueDictionary();
        redirectTargetDictionary.Add("action", "Index");
        redirectTargetDictionary.Add("controller", "Home");

        filterContext.Result = new RedirectToRouteResult(redirectTargetDictionary);
    }
}

16
Або простоnew RedirectToRouteResult(new RouteValueDictionary { { "controller", "Home" }, {"action", "HomePage" } })
Доменік

13
Якби ти міг сказати цей коментар із зеленим підкресленням
CRice",

1
Ви також можете помістити цей код у OnExceptionметод, якщо ви встановилиfilterContext.ExceptionHandled = true;
demoncodemonkey

1

Я знаю, що трохи запізнився на вечірку, але я використав рішення veggerby та створив допоміжний клас, який може бути корисним для деяких людей, тому я хотів надати його тут:

public static class ActionFilterHelpers
{
    public static void Redirect(this ActionExecutingContext filterContext, String controller, String action, object routeValues)
    {
        filterContext.Result = Redirect(controller, action, routeValues);
    }

    public static ActionResult Redirect(String controller, String action, object routeValues)
    {
        var routeValues = new RouteValueDictionary();

        routeValues["controller"] = controller;
        routeValues["action"] = action;

        foreach (var keyValue in new ObjectDictionary(routeValues))
            routeValues.Add(keyValue.Key, keyValue.Value);

        return new RedirectToRouteResult(routeValues);
    }
}

Я надав як статичний метод, який повертає переспрямування, так ActionResultі метод розширення, який розширюється filterContext. Сподіваюся, хтось вважає це корисним.

ObjectDictionaryце клас, який використовує відображення для створення словника із властивостей об’єкта, з якого він побудований. Я не включив цей код, оскільки вважаю, що є кращий спосіб зробити це десь у фреймворці. Я ще не знайшов, але не хочу, щоб інші успадковували мої потенційні помилки.


0

Фільтри безпеки / авторизації / автентифікації повинні використовувати AuthorizeAttribute та IAuthorizationFilter .

public class IsGuestAttribute: AuthorizeAttribute, IAuthorizationFilter
{
    public void OnResultExecuted(ResultExecutedContext filterContext)
    {
    }
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (!Ctx.User.IsGuest) 
        {
            filterContext.Result = new RedirectToRouteResult(
                new RouteValueDictionary 
                { 
                    { "controller", "Home" }, 
                    { "action", "Index" } 
                });
        }
    }
}

0

Використання: filterContext.RedirectToAction("Login", "Account");

Ось допоміжний клас, який я написав із написаними деякими методами розширення, щоб забезпечити функціональність RedirectToAction у більшій кількості місць. Для ОП це занадто пізно, але, сподіваємось, це допоможе комусь!

public static class RedirectHelper
{
    // RedirectToAction Extension Methods
    public static void RedirectToAction(this HttpResponseBase response, String action, String controller, object routeValues = null, bool endResponse = false)
    {
        response.RedirectToRoute(CreateRoute(action, controller, routeValues));
        if (endResponse) response.End();
    }
    public static void RedirectToAction(this HttpResponse response, String action, String controller, object routeValues = null, bool endResponse = false)
    {
        response.RedirectToRoute(CreateRoute(action, controller, routeValues));
        if (endResponse) response.End();
    }
    public static void RedirectToAction(this ActionExecutingContext filterContext, String action, String controller, object routeValues = null, bool endResponse = false)
    {
        if (endResponse) filterContext.HttpContext.Response.RedirectToAction(action, controller, routeValues, true);
        else filterContext.Result = new RedirectToRouteResult(CreateRoute(action, controller, routeValues));
    }
    public static void RedirectToAction(this ExceptionContext filterContext, String action, String controller, object routeValues = null, bool endResponse = false)
    {
        if (endResponse) filterContext.HttpContext.Response.RedirectToAction(action, controller, routeValues, true);
        else {
            filterContext.ExceptionHandled = true;
            filterContext.Result = new RedirectToRouteResult(CreateRoute(action, controller, routeValues));
        }
    }
    // Route Value Derivation
    public static RouteValueDictionary CreateRoute(String action, String controller, object routeValues = null)
    {
        RouteValueDictionary result = routeValues != null ? 
            HtmlHelper.AnonymousObjectToHtmlAttributes(routeValues) : 
            new RouteValueDictionary();
        result["controller"] = controller;
        result["action"] = action;
        return result;
    }
}

Є більше ControllerContexts, які не включені, але додати свій власний за вашими потребами має бути досить просто.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.