如何将变量从ActionFilter传递到C#MVC中的Controller Action?

时间:2016-08-09 13:34:16

标签: c# asp.net asp.net-mvc action-filter actionfilterattribute

采用简单的操作过滤器,检查用户是否已登录并检索其用户ID。

public class LoginFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {    
        // Authenticate (somehow) and retrieve the ID
        int id = Authentication.SomeMethod();
        // Pass the ID through to the controller?
        .....
    }
}

我怎么能把这个ID传递给我的控制器动作?

[LoginFilter]
public class Dashboard : Controller
{
    public ActionResult Index()
    {
        // I'd like to be able to use the ID from the LoginFilter here
        int id = ....
    }
}

是否有相当于ViewBag可以让我这样做?或者其他一些允许我在过滤器和控制器动作之间传递变量和对象的技术?

4 个答案:

答案 0 :(得分:7)

我相信ActionExecutingContext包含对调用控制器的引用。使用这个与从基类Controller类派生的自定义控制器类混合然后将id存储为控制器的实例变量可能会这样做。

自定义控制器

Public Class MyController : Controller
{
    Public int Id {get;set;}
}

LoginFilter

public class LoginFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {    
        // Authenticate (somehow) and retrieve the ID
        int id = Authentication.SomeMethod();
        ((MyController)filterContext.Controller).Id = id; 
        //Assign the Id by casting the controller (you might want to add a if ... is MyController before casting)
    }
}

控制器

[LoginFilter]
public class Dashboard : MyController
{
    public ActionResult Index()
    {
        //Read the Id here
        int id = this.Id
    }
}

答案 1 :(得分:7)

您可以像这样使用ViewData/ViewBag

1。)使用ViewData

注意:如果是ViewData,您需要执行一个步骤,即必须对其进行类型转换

public class LoginFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {    
        // Authenticate (somehow) and retrieve the ID
        int idValue = Authentication.SomeMethod();

        // Pass the ID through to the controller?
        filterContext.Controller.ViewData.Add("Id", idValue);
    }
}

然后在Controller函数

[LoginFilter]
public class Dashboard : Controller
{
    public ActionResult Index()
    {
        // I'd like to be able to use the ID from the LoginFilter here
        int id = (int)ViewData["Id"];
    }
}

2。)使用ViewBag

public class LoginFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {    
        // Authenticate (somehow) and retrieve the ID
        int idValue = Authentication.SomeMethod();

        // Pass the ID through to the controller?

        filterContext.Controller.ViewBag.Id = idValue; 
    }
}

然后在控制器中

[LoginFilter]
public class Dashboard : Controller
{
    public ActionResult Index()
    {
        // I'd like to be able to use the ID from the LoginFilter here
        int id = ViewBag.Id;
    }
}

答案 2 :(得分:6)

您可以通过以下方式使用ViewBag

filterContext.Controller.ViewBag.Id = id;

应该这样做,一旦你filterContext.Controller,你就可以访问其中的所有字段,例如TempData

即便如此,如果您使用的是OWIN,那么也许可以获取用户的ID,您可以使用具有扩展方法的Controller.User来获取Id和属性获得大多数其他标准数据,如Name等。

答案 3 :(得分:0)

这是我在较旧的应用程序中看到的一种方法,避免使用viewbag,而是使控制器参数指定期望的值:

public class LoginFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {    
        // Authenticate (somehow) and retrieve the ID
        int id = Authentication.SomeMethod();
        
        // Check if there's an action parameter on the controller: set it to your ID
        if (filterContext.ActionParameters.ContainsKey("authId"))
        {
            filterContext.ActionParameters["authId"] = id;
        }
    }
}

[LoginFilter]
public class Dashboard : Controller
{
    public ActionResult Index(int authId)
    {
        // authId parameter is available to each action bearing LoginFilter
        // It's instantiated if it's present in the method signature
        ...
    }
}