Каков наилучший способ сделать перенаправление в 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"