从动作过滤器属性重定向
Posted
技术标签:
【中文标题】从动作过滤器属性重定向【英文标题】:Redirect From Action Filter Attribute 【发布时间】:2011-07-24 03:00:32 【问题描述】:在ActionFilterAttribute
中进行重定向的最佳方式是什么?我有一个名为IsAuthenticatedAttributeFilter
的ActionFilterAttribute
,它检查了会话变量的值。如果变量为 false,我希望应用程序重定向到登录页面。我更喜欢使用路由名称SystemLogin
进行重定向,但是此时任何重定向方法都可以。
【问题讨论】:
Check this answer. Hope this will help you. 【参考方案1】:设置 filterContext.Result
带有路线名称:
filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues);
你也可以这样做:
filterContext.Result = new ViewResult
ViewName = SharedViews.SessionLost,
ViewData = filterContext.Controller.ViewData
;
如果你想使用RedirectToAction
:
您可以在您的控制器(最好在其基本控制器)上创建一个公开的RedirectToAction
方法,该方法只需从System.Web.Mvc.Controller
调用受保护的RedirectToAction
。添加此方法允许从过滤器公开调用 your 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");
【讨论】:
这可行,但不应该有可用的 RedirectToAction 方法吗? @BenMills,但是,它是protected
,因此您无法通过过滤器访问它。
我现在的问题是为什么微软决定做这个过滤器protected
一定有一些合理的解释?重新定义 RedirectToAction
的可访问性,我觉得很肮脏,不明白为什么首先要封装它。
@MatthewMarlin - 请参阅 Syakur 的答案以获得重定向到操作的正确答案。你是正确的,你不应该直接从动作过滤器调用控制器——这就是紧耦合的定义。
@Akbari 您是否尝试过设置属性的 Order 属性? FilterScope 也会影响执行顺序。【参考方案2】:
或者重定向,如果它调用你自己的代码,你可以使用这个:
actionContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new controller = "Home", action = "Error" )
);
actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);
这不是纯粹的重定向,但会产生类似的结果而没有不必要的开销。
【讨论】:
你确实帮助了我。谢谢! 请注意,您不应在操作过滤器中调用actionContext.Result.ExecuteResult
- MVC 将在操作过滤器运行后自动执行此操作(前提是 actionContext.Result
不为空)。【参考方案3】:
我正在使用 MVC4,我使用以下方法在违反授权时重定向自定义 html 屏幕。
扩展AuthorizeAttribute
说CutomAuthorizer
覆盖OnAuthorization
和HandleUnauthorizedRequest
在RegisterGlobalFilters
中注册CustomAuthorizer
。
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 和一个answer,这里有更多关于 SO 的详细信息。
【讨论】:
【参考方案5】:试试下面的sn-p,应该很清楚了:
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);
【讨论】:
这对我有用,如果任何用户尝试更改查询字符串值并尝试访问未经授权的数据,我必须检查查询字符串值,而不是将它们重定向到未经授权的消息页面,使用 ActionFilterAttribute。【参考方案6】:如果您使用 Ajax 请求,这里也有一个解决方案。
using System;
using System.Web.Mvc;
using System.Web.Routing;
namespace YourNamespace
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeCustom : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext context)
if (YourAuthorizationCheckGoesHere)
string area = "";// leave empty if not using area's
string controller = "ControllerName";
string action = "ActionName";
var urlHelper = new UrlHelper(context.RequestContext);
if (context.HttpContext.Request.IsAjaxRequest()) // Check if Ajax
if(area == string.Empty)
context.HttpContext.Response.Write($"<script>window.location.reload('urlHelper.Content(System.IO.Path.Combine(controller, action))');</script>");
else
context.HttpContext.Response.Write($"<script>window.location.reload('urlHelper.Content(System.IO.Path.Combine(area, controller, action))');</script>");
else // Non Ajax Request
context.Result = new RedirectToRouteResult(new RouteValueDictionary( new area, controller, action ));
base.OnActionExecuting(context);
【讨论】:
【参考方案7】:这对我有用(asp.net core 2.1)
using JustRide.Web.Controllers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
namespace MyProject.Web.Filters
public class IsAuthenticatedAttribute : ActionFilterAttribute
public override void OnActionExecuting(ActionExecutingContext context)
if (context.HttpContext.User.Identity.IsAuthenticated)
context.Result = new RedirectToActionResult(nameof(AccountController.Index), "Account", null);
[AllowAnonymous, IsAuthenticated]
public IActionResult Index()
return View();
【讨论】:
【参考方案8】:你可以继承你的控制器,然后在你的动作过滤器中使用它
在 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);
缺点。这就是将所有控制器更改为从“MyController”类继承
【讨论】:
以上是关于从动作过滤器属性重定向的主要内容,如果未能解决你的问题,请参考以下文章