从操作筛选器属性重定向

rya*_*zec 131 c# asp.net-mvc redirect routes asp.net-mvc-3

在一个地方进行重定向的最佳方法是什么ActionFilterAttribute?我有一个ActionFilterAttribute调用IsAuthenticatedAttributeFilter并检查会话变量的值.如果变量为false,我希望应用程序重定向到登录页面.我更喜欢使用路由名称SystemLogin重定向,但此时任何重定向方法都可以.

CRi*_*ice 180

设置filterContext.Result

使用路线名称:

filterContext.Result = new RedirectToRouteResult("SystemLogin", routeValues);
Run Code Online (Sandbox Code Playgroud)

你也可以这样做:

filterContext.Result = new ViewResult
{
    ViewName = SharedViews.SessionLost,
    ViewData = filterContext.Controller.ViewData
};
Run Code Online (Sandbox Code Playgroud)

如果你想使用RedirectToAction:

你可以做一个公共RedirectToAction方法控制器上(最好是在它的基本控制器简单地调用保护)RedirectToActionSystem.Web.Mvc.Controller.添加此方法允许从过滤器公开呼叫 RedirectToAction.

public new RedirectToRouteResult RedirectToAction(string action, string controller)
{
    return base.RedirectToAction(action, controller);
}
Run Code Online (Sandbox Code Playgroud)

然后你的过滤器看起来像:

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

  • 我现在的问题是为什么微软决定让这个过滤器"受保护",必须有一些合理的解释?我觉得非常脏,重新定义了`RedirectToAction`的这种可访问性,却没有理解为什么它首先封装了. (10认同)
  • 这有效,但是不应该有RedirectToAction方法吗? (8认同)
  • @MatthewMarlin - 查看Syakur的答案,找到重定向到某个动作的正确答案.你是正确的,你不应该直接从动作过滤器调用控制器 - 这是紧耦合的定义. (2认同)

Sya*_*man 75

作为重定向的替代方案,如果它正在调用您自己的代码,您可以使用:

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

actionContext.Result.ExecuteResult(actionContext.Controller.ControllerContext);
Run Code Online (Sandbox Code Playgroud)

它不是纯粹的重定向,而是提供类似的结果,没有不必要的开销.

  • 请注意,您不应该在动作过滤器中调用`actionContext.Result.ExecuteResult` - MVC将在动作过滤器运行后自动执行此操作(如果`actionContext.Result`不为null). (21认同)

小智 12

我正在使用MVC4,我使用以下方法在授权违规时重定向自定义html屏幕.

延伸AuthorizeAttributeCutomAuthorizer 覆盖OnAuthorizationHandleUnauthorizedRequest

注册CustomAuthorizerRegisterGlobalFilters.

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{

    filters.Add(new CustomAuthorizer());
}
Run Code Online (Sandbox Code Playgroud)

识别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" }

                                         });

    }
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*han 9

听起来你想重新实现,或者可能扩展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);
    }
}
Run Code Online (Sandbox Code Playgroud)

有一个很好的问题,答案中有更详细的信息.


Muh*_*man 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);
  }
}
Run Code Online (Sandbox Code Playgroud)