Перенаправление из атрибута фильтра действия

Каков наилучший способ сделать перенаправление в ActionFilterAttribute. У меня есть ActionFilterAttribute, называемый IsAuthenticatedAttributeFilter и который проверяет значение переменной сеанса. Если переменная имеет значение false, я хочу, чтобы приложение перенаправлялось на страницу входа. Я бы предпочел переадресовать с использованием имени маршрута SystemLogin, однако любой метод переадресации в этой точке был бы прав.

Ответ 1

Установить filterContext.Result

С именем маршрута:

filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues);

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

filterContext.Result = new ViewResult
{
    ViewName = SharedViews.SessionLost,
    ViewData = filterContext.Controller.ViewData
};

Если вы хотите использовать RedirectToAction:

Вы можете сделать общедоступный метод RedirectToAction на вашем контроллере (желательно на его базовом контроллере), который просто вызывает защищенный RedirectToAction от System.Web.Mvc.Controller. Добавление этого метода позволяет публично вызывать ваш RedirectToAction из фильтра.

public new RedirectToRouteResult RedirectToAction(string action, string controller)
{
    return base.RedirectToAction(action, controller);
}

Тогда ваш фильтр будет выглядеть примерно так:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var controller = (SomeControllerBase) filterContext.Controller;
    filterContext.Result = controller.RedirectToAction("index", "home");
}

Ответ 2

В качестве альтернативы перенаправлению, если он вызывает ваш собственный код, вы можете использовать это:

actionContext.Result = new RedirectToRouteResult(
    new RouteValueDictionary(new { controller = "Home", action = "Error" })
);

actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);

Это не чистое перенаправление, но дает аналогичный результат без лишних накладных расходов.

Ответ 3

Я использую MVC4, я использовал следующий подход для перенаправления пользовательского html-экрана при нарушении авторизации.

Расширить AuthorizeAttribute сказать CutomAuthorizer переопределите OnAuthorization и HandleUnauthorizedRequest

Зарегистрируйте CustomAuthorizer в RegisterGlobalFilters.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}

после идентификации вызова доступа unAuthorized HandleUnauthorizedRequest и перенаправления на соответствующее действие контроллера, как показано ниже.


public class CustomAuthorizer : AuthorizeAttribute
{

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        bool isAuthorized = IsAuthorized(filterContext); // check authorization
        base.OnAuthorization(filterContext);
        if (!isAuthorized && !filterContext.ActionDescriptor.ActionName.Equals("Unauthorized", StringComparison.InvariantCultureIgnoreCase)
            && !filterContext.ActionDescriptor.ControllerDescriptor.ControllerName.Equals("LogOn", StringComparison.InvariantCultureIgnoreCase))
        {

            HandleUnauthorizedRequest(filterContext);

        }
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result =
       new RedirectToRouteResult(
           new RouteValueDictionary{{ "controller", "LogOn" },
                                          { "action", "Unauthorized" }

                                         });

    }
}

Ответ 4

Похоже, вы хотите повторно реализовать или, возможно, расширить, AuthorizeAttribute. Если это так, вы должны убедиться, что вы наследуете это, а не ActionFilterAttribute, чтобы позволить ASP.NET MVC сделать больше работы для вас.

Кроме того, вы хотите убедиться, что авторизуетесь, прежде чем выполнять какую-либо реальную работу в методе действий. В противном случае единственная разница между входами и не будет той страницей, которую вы видите, когда работа будет выполнена.

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        // Do whatever checking you need here

        // If you want the base check as well (against users/roles) call
        base.OnAuthorization(filterContext);
    }
}

Существует хороший question с ответом с более подробной информацией о SO.

Ответ 5

Попробуйте следующий фрагмент, это должно быть довольно ясно:

public class AuthorizeActionFilterAttribute : ActionFilterAttribute
{
  public override void OnActionExecuting(FilterExecutingContext filterContext)
  {
    HttpSessionStateBase session = filterContext.HttpContext.Session;
    Controller controller = filterContext.Controller as Controller;

    if (controller != null)
    {
      if (session["Login"] == null)
      {
        filterContext.Cancel = true;
        controller.HttpContext.Response.Redirect("./Login");
      }
    }

    base.OnActionExecuting(filterContext);
  }
}

Ответ 6

вы можете наследовать свой контроллер, а затем использовать его внутри фильтра действий

внутри класса ActionFilterAttribute:

   if( filterContext.Controller is MyController )
      if(filterContext.HttpContext.Session["login"] == null)
           (filterContext.Controller as MyController).RedirectToAction("Login");

внутри вашего базового контроллера:

public class MyController : Controller 
{
    public void  RedirectToAction(string actionName) { 
        base.RedirectToAction(actionName); 
    }
}

Cons. это изменение всех контроллеров для наследования класса "MyController"