从ActionFilterAttribute设置ViewBag

时间:2016-03-14 21:18:01

标签: asp.net-core asp.net-core-mvc

网站我正在创建可由用户设置的自定义颜色(仅限某些页面)。我想在ActionFilterAttribute中获取该数据并将其设置在ViewBag中,以便我可以在_Layout.cshtml中获取数据。

这是我的ActionFilterAttribute ...

public class PopulateColorOptionsAttribute : ActionFilterAttribute
{
    private readonly OptionsDataHelper optionsDataHelper;

    public PopulateOptionsAttribute(OptionsDataHelper optionsDataHelper)
    {
        this.optionsDataHelper = optionsDataHelper;
    }

    public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        await base.OnActionExecutionAsync(context, next);

        // Get the cemetery data and set it on the view bag.
        var personId = Convert.ToInt32(context.RouteData.Values["personId"]);
        context.Controller.ViewBag.OptionsData = await optionsDataHelper.GetValueAsync(personId, CancellationToken.None);
    }
}

不幸的是,我在ViewBag上收到一条错误,指出:

  

'对象'不包含' ViewBag'的定义没有扩展方法' ViewBag'接受类型'对象'的第一个参数。可以找到(你错过了使用指令或汇编引用吗?)[dnx451]

我很确定我没有正确理解过滤器的内容,我希望能够指导如何实现我想要做的事情。

2 个答案:

答案 0 :(得分:14)

ActionExecutingContext.Controller被声明为Object类型,因为该框架并未对哪些类可以作为控制器施加任何限制。

如果您始终创建继承自基础Controller类的控制器,则可以在过滤器中使用该假设并将context.Controller转换为Controller

public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
    await base.OnActionExecutionAsync(context, next);

    var controller = context.Controller as Controller;
    if (controller == null) return;
    controller.ViewBag.Message = "Foo message";    
}

如果你不能做出这个假设,那么你可以使用类似的方法检查上下文中的结果:

public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
    var viewResult = context.Result as ViewResult; //Check also for PartialViewResult and ViewComponentResult
    if (viewResult == null) return;
    dynamic viewBag = new DynamicViewData(() => viewResult.ViewData);
    viewBag.Message = "Foo message";

    await base.OnResultExecutionAsync(context, next);
}

答案 1 :(得分:0)

将context.Controller转换为Controller

尝试更改以下行

context.Controller.ViewBag.OptionsData = await optionsDataHelper.GetValueAsync(personId, CancellationToken.None);

((Controller)(context.Controller)).ViewBag.OptionsData = await optionsDataHelper.GetValueAsync(personId, CancellationToken.None);