繁体   English   中英

如何在 C# MVC 中将变量从 ActionFilter 传递到控制器操作?

[英]How do I pass a variable from an ActionFilter to a Controller Action in C# MVC?

采用一个简单的操作过滤器,它检查用户是否登录并检索他们的用户 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 的东西可以让我这样做? 或者其他一些允许我在过滤器和控制器操作之间传递变量和对象的技术?

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

自定义控制器

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

登录过滤器

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

您可以像这样使用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);
    }
}

然后在控制器功能中

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

您可以通过执行以下操作来使用ViewBag

filterContext.Controller.ViewBag.Id = id;

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

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

这是我在旧应用程序中看到的一种方法,它避免使用 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
        ...
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM