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

问题描述 投票:0回答:5

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

c# asp.net asp.net-mvc action-filter actionfilterattribute
5个回答
15
投票

我相信

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

10
投票

您可以像这样使用

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

7
投票

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

ViewBag

filterContext.Controller.ViewBag.Id = id;

应该可以,一旦你这样做了

filterContext.Controller
,你就可以访问其中的所有字段,就像
TempData
一样。

即便如此,如果您使用

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


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

0
投票

我相信,使用控制器 - ViewData 或 ViewBag 是错误的解决方案。

定义一个具有所需属性的小类,并通过服务注册该类。

class LittleClass
{
    public string WhatEver {get;set;}
}

关于服务

services.AddScoped<LittleClass>();

现在您可以在 Filter 和 Controller 上使用依赖注入

public class YourFilter : ActionFilterAttribute
{
    private LittleClass _c;
    public YourFilter(LittleClass c)
    {
        _c = c;
    }
    
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        //manipulate _c
        _c.WhatEver = "TEST";
        base.OnActionExecuting(context);
    }
}

通过控制器中的依赖注入实现相同的效果。

class YourController
{

    private LittleClass _c;

    public YourController(LittleClass c)
    {
        _c = c;
        Console.WriteLine( _c.WhatEver ); // => TEST
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.