简体   繁体   English

是否可以在“动作过滤器”中使用“动作方法”中的数据?

[英]Is it possible to make data from an Action Method available in an Action Filter?

The Background: 的背景:

We are supplied with html files - 'wrappers' - from our client, into which we need to inject the content that we produce. 我们从客户端提供了html文件-“包装器”,我们需要将产生的内容注入其中。 They have different wrappers for different pages and we have to inject the corresponding content into a special tag that they supply in the wrapper. 他们为不同的页面使用不同的包装器,我们必须将相应的内容注入到包装器中提供的特殊标签中。

The wrapper file name corresponds to the name of the action method. 包装文件的名称与操作方法的名称相对应。 So for the example below, a custom action filter is executed which will determine the name of the wrapper and then call a method in the BaseController (which every controller implements) which will load the wrapper and inject our content into it. 因此,对于下面的示例,将执行一个自定义操作过滤器,该过滤器将确定包装器的名称,然后在BaseController中调用一个方法(每个控制器都实现该方法),该方法将加载包装器并将我们的内容注入其中。

    [WrapperAction]
    public ActionResult Home()
    {
        return View();
    }

The reason I put this in an ActionFilter is because I didn't want to be calling the BaseController 's method to populate the wrapper in every action method that needed a wrapper. 我将其放入ActionFilter的原因是,我不想调用BaseController的方法来在每个需要包装器的操作方法中填充包装器。 I thought it was much tidier to decorate the method with the ActionFilterAttribute 我认为用ActionFilterAttribute装饰方法要整整齐齐

WrapperAction is defined as follows: WrapperAction的定义如下:

public class WrapperAction : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext aec)
    {
        var baseController = (BaseController)filterContext.Controller;

        string wrapper = aec.RequestContext.RouteData.Values["action"].ToString();

        baseController.PopulateWrapper(wrapper);
    }
}

and PopulateWrapper is defined as 并且PopulateWrapper被定义为

    public void PopulateWrapper(string wrapperName)
    {
        // get wrapper file from disk
        Wrapper wrapper = _wrapperService.GetWrapper(Site.Id, wrapperName);

        // populate the file with our CSS (it already has its own pre-populated CSS)
        // our CSS file is determined by the id of a Site object.
        AppHelper.PopulateWrapperCss(wrapper, this.Site.Id);

        // make wrapper sections available to the Master page, 
        // split so that we can place our content around them
        ViewData["WrapperTop"] = wrapper.WrapperTop;
        ViewData["WrapperMiddle"] = wrapper.WrapperMiddle;
        ViewData["WrapperBottom"] = wrapper.WrapperBottom;
    }

The Dilema: Dilema:

Now however, a new requirement has come in. There are some new tags in the wrapper that I need to populate, and I have to populate them with different data depending on the action method that calls the wrapper. 但是,现在有了新的要求。包装器中需要填充一些新标签,根据调用包装器的操作方法,我必须用不同的数据填充它们。 That data is determined in the action methods, but the data needs to be used in the PopulateWrapper method that gets called by the WrapperAction . 该数据是在操作方法中确定的,但是该数据需要在WrapperAction调用的PopulateWrapper方法中使用。

I now need to have a method similar to 我现在需要一种类似于

AppHelper.PopulateWrapperTags(wrapper, this.TagData);

and I need to have some way for BaseController's TagData property to be populated with data. 而且我需要某种方法来用数据填充BaseController的TagData属性。 I can asign the property in the action method like follows 我可以在动作方法中分配属性,如下所示

    [WrapperAction]
    public ActionResult Home()
    {
        base.TagData = GetTagData();
        return View();
    }

but that kind of defeats the point of me having the WrapperAction in the first place because I don't want to have to be referring to the BaseController like that. 但这有点使我失去WrapperAction的目的,因为我不想像这样那样引用BaseController。

The Question: 问题:

Is there a way for me to supply WrapperAction with the data it needs to populate the wrapper with? 有没有办法为WrapperAction提供填充包装器所需的数据? Do I need to take the hit and start calling 我需要点击并开始打电话吗

        var tagData = GetTagData();
        string wrapperName = RouteData.Values["action"].ToString();
        base.PopulateWrapper(wrapperName, tagData);

in every controller? 在每个控制器中? Is there a better way for me to do this? 我有更好的方法吗?

What you have already written is really very good and needs only slight adjustment to meet your new requirement. 您已经写的东西真的非常好,只需稍作调整即可满足您的新要求。

The key is that your action filter is a type of OnActionExecuted which runs after your action code has completed, but before the view is executed. 关键是您的动作过滤器是OnActionExecuted类型,它您的动作代码完成之后但执行视图之前运行。 Therefore the filter method can build on whatever has taken place within the action method. 因此,筛选器方法可以建立在操作方法内发生的任何事情上。

To achieve your requirement, create the tagData variable within your base controller, so that the controllers that inherit from it can populate it if necessary. 为了满足您的要求,请在基本控制器中创建tagData变量,以便从其继承的控制器可以在必要时填充该变量。

Then, within your action filter you simply need something like 然后,在动作过滤器中,您只需要

if (tagData == null)
   baseController.PopulateWrapper(wrapper)
else
   baseController.PopulateWrapper(wrapper, tagData)

I'm sure you get the general idea. 我敢肯定,你有大致的想法。

imho the following was just right, so I don't see how the action filter is tidier: 恕我直言,以下内容是正确的,因此我看不到动作过滤器如何整理:

public ActionResult Home()
{
   PopulateWrapper();
   return View();
}

and in the controller base: 并在控制器库中:

public void PopulateWrapper(string wrapperName)
{
   string wrapperName = RouteData.Values["action"].ToString();
   //... rest of populate wrapper

then you go: 然后你去:

public ActionResult Home()
{
    PopulateWrapper(GetTagData()); // after defining an overload in base
    return View();
}

Assuming you still go the action filter way, I don't see why you are forcing the dependency with controller base with it ie why the PopulateWrapper is in controller base. 假设您仍然使用动作过滤器方式,那么我看不出您为什么要使用控制器基来强制依赖,即为什么PopulateWrapper在控制器基中。

Note that you can also pass the data in ViewData, but that feels worst in your scenario - specially given the dependency in controller base. 请注意,您也可以在ViewData中传递数据,但这在您的情况下感觉很糟-特别是考虑到控制器库中的依赖关系。

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

相关问题 将方法返回的值传递给操作过滤器 - pass value returned from a method to action filter 从动作过滤器调用控制器方法 - Call controller method from action filter 来自服务层的方法在控制器动作方法中不可用 - Method from service layer is not available in controller action method 动态将动作过滤器添加到特定的动作方法 - Add an action filter dynamically to specific action method 可以调用操作方法(从操作方法)并让ASP.Net Core注入[FromQuery]参数吗? - Possible to call action method (from action method) and let ASP.Net Core inject [FromQuery] params? 是否可以使用数据注释来验证传递给 Controller 的 Action 方法的参数? - Is it possible to use Data Annotations to validate parameters passed to an Action method of a Controller? 如何创建过滤器以防止操作方法找到空对象 - How to create a filter to prevent action method from finding null objects 如何将参数从动作过滤器传递到控制器方法 - How to pass a parameter from action filter to a controller method C# - 是否可以从Action中获取方法的所有者类型? - C# - Is it possible to get the owner type of a method from an Action? 从HttpGet操作方法获取数据并将其传递给HttpPost方法 - Get Data from HttpGet Action Method and pass them to HttpPost Method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM