2011-03-27 46 views
106

ActionFilterAttribute中執行重定向的最佳方式是什麼?我有一個名爲IsAuthenticatedAttributeFilterActionFilterAttribute並檢查了會話變量的值。如果該變量爲false,我希望應用程序重定向到登錄頁面。我寧願使用路由名稱SystemLogin重定向,但是此時任何重定向方法都可以。從動作重定向過濾器屬性

+2

** [檢查這個答案。希望這會對你有所幫助。](http://stackoverflow.com/a/18126733/2015869)** – 2013-08-12 08:53:51

回答

152

集filterContext.Result

隨着路由名稱:

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

你也可以這樣做:

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

如果你想使用RedirectToAction

你可以做(​​最好是在它的基礎控制器),簡單地調用從System.Web.Mvc.Controller保護RedirectToAction您的控制器上的公共RedirectToAction方法。添加此方法允許從過濾器公開呼叫 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"); 
} 
+7

這可行,但不應該有一個RedirectToAction方法可用? – 2012-02-21 19:28:35

+0

@BenMills然而,它是'受保護的',所以你不能從過濾器訪問它。 – James 2014-02-15 10:14:42

+7

我現在的問題是爲什麼微軟決定讓這個過濾器保護'必須有一些合理的解釋?我覺得非常髒,重新定義'RedirectToAction'的這種可訪問性,而不理解它爲什麼被封裝在第一位。 – 2015-03-25 11:30:50

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); 
    } 
} 

有一個很好的questionanswer與這裏SO更多細節。

4

試試下面的代碼片段,它應該是很清楚的:

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); 
    } 
} 
+0

這對我有用,如果任何用戶試圖更改查詢字符串值並嘗試訪問未授權給他/她的數據,則我必須檢查查詢字符串值,而不是使用ActionFilterAttribute將其重定向到未授權的消息頁面。 – Sameer 2013-05-23 06:56:28

+0

這很好。謝謝! – 2013-06-07 15:43:28

1

,你可以繼承你的控制器,然後用它你的動作過濾器

裏面你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的」類繼承

56

另外一個重定向,如果調用自己的代碼,你可以這樣做:

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

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

它不是一個純粹的重定向,但給出了類似的結果沒有不必要的開銷

+0

你幫我。謝謝! – 2015-01-08 16:13:59

+0

這是正確的答案。 – 2015-02-27 15:09:27

+12

請注意,您不應該在您的操作過濾器內調用actionContext.Result.ExecuteResult - MVC將在操作過濾器運行後自動執行此操作(提供的actionContext.Result不爲空)。 – NightOwl888 2016-02-24 19:41:58

10

我正在使用MVC4,我使用以下方法在授權違反時重定向自定義html屏幕。

擴展AuthorizeAttributeCutomAuthorizer 覆蓋的OnAuthorizationHandleUnauthorizedRequest

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

             }); 

    } 
}