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

Jon*_*ory 6 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?
        .....
    }
}
Run Code Online (Sandbox Code Playgroud)

我怎么能把这个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 = ....
    }
}
Run Code Online (Sandbox Code Playgroud)

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

Fra*_*ord 7

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

定制控制器

Public Class MyController : Controller
{
    Public int Id {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

调节器

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


Lui*_*iso 7

您可以使用以下ViewBag方式:

filterContext.Controller.ViewBag.Id = id;
Run Code Online (Sandbox Code Playgroud)

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

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


小智 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在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"];
    }
}
Run Code Online (Sandbox Code Playgroud)

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

然后在控制器中

[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;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,虽然我最终使用了 TempData(如@luiso 的回答所建议的那样)而不是 ViewBag 或 ViewData,但您提供了有关如何实际使用它的最佳细节以及示例,并且 ViewBag 的技术与对于临时数据。我认为这是临时数据,而不是用于视图的任何内容,因此使用 TempData 更合乎逻辑 (2认同)

Lov*_*gun 6

这是我在旧应用程序中看到的一种方法,避免使用 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
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)