在ASP.NET MVC Core控制器的构造函数中设置ViewBag属性 [英] Set ViewBag property in the constructor of a ASP.NET MVC Core controller

查看:95
本文介绍了在ASP.NET MVC Core控制器的构造函数中设置ViewBag属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的主题有点面包屑.控制器始终是类别.为了避免重复我自己,我想在控制器的构造函数中为所有此类操作设置它:

My theme has some sort of breadcrumb. The controller is always the category. To avoid repeat myself, I want to set it in the constructor of the controller for all actions like this:

class MyController:Controller{
    public MyController() {
        ViewBag.BreadcrumbCategory = "MyCategory";
    }
}

当我在布局视图中访问 ViewBag.BreadcrumbCategory 时,其为null.在一个动作中它起作用:

When I access ViewBag.BreadcrumbCategory in the layout-view, its null. In a Action it works:

class MyController:Controller{
    public IActionResult DoSomething() {
        ViewBag.BreadcrumbCategory = "MyCategory";
    }
}

我想知道在构造函数中无法设置ViewBag属性吗?在执行此工作的每个动作上都调用一个函数会很烦人,也没有好的习惯.在另一个问题中,使用构造函数是公认的答案,但是正如我所说,这是行不通的,至少对于ASP.NET Core而言.

I'm wondering that setting a ViewBag property is not possible in a constructor? It would be annoying and no good practice to have a function called on every action which do this work. In another question using the constructor was an accepted answear, but as I said this doesn't work, at least for ASP.NET Core.

推荐答案

有一个 GitHub问题关于它,并指出这是设计使然.您链接的答案是有关ASP.NET MVC3(旧的传统ASP.NET堆栈)的.

There is an GitHub issue about it and it's stated that this is by design. The answer you linked is about ASP.NET MVC3, the old legacy ASP.NET stack.

ASP.NET Core是从零开始编写的,并使用了不同的概念,旨在为可移植性(多个平台)以及性能和现代实践(例如对依赖项注入的内置支持)而设计.

ASP.NET Core is written from scratch and uses different concepts, designed for both portability (multiple platforms) as well as for performance and modern practices like built-in support for Dependency Injection.

最后一个使得不可能在构造函数中设置 ViewBag ,因为 Constructor 基类的某些属性必须通过Property Injection注入,因为您可能已经注意到您不必在派生的控制器中传递这些依赖项.

The last one makes it impossible to set ViewBag in the constructor, because certain properties of the Constructor base class must be injected via Property Injection as you may have noticed that you don't have to pass these dependencies in your derived controllers.

这意味着,当调用 Controller 的构造函数时,未设置 HttpContext ControllerContext 等的属性.仅在调用构造函数之后设置它们,并且存在对该对象的有效实例/引用.

This means, when the Controller's constructor is called, the properties for HttpContext, ControllerContext etc. are not set. They are only set after the constructor is called and there is a valid instance/reference to this object.

并且正如GitHub问题中指出的那样,由于它是设计使然,因此无法修复.

And as pointed in the GitHub issues, it won't be fixed because this is by design.

您可以看到,则它将创建 DynamicViewData 类的新实例,该实例将在构造函数初始化后替换为该实例..

As you can see here, ViewBag has a dependency on ViewData and ViewData is populated after the controller is initialized. If you call ViewBag.Something = "something", then you it will create a new instance of the DynamicViewData class, which will be replaced by the one after the constructor gets initialized.

正如@SLaks指出的那样,您可以使用为每个控制器配置的动作过滤器.

As @SLaks pointed out, you can use an action filter which you configure per controller.

以下示例假定您始终 Controller 基类派生控制器.

The following example assumes that you always derive your controllers from Controller base class.

public class BreadCrumbAttribute : IActionFilter
{
    private readonly string _name;

    public BreadCrumbAttribute(string name)
    {
        _name = name;
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        base.OnActionExecuting(context);

        var controller = context.Controller as Controller;
        if (controller != null) 
        {
            controller.ViewBag.BreadcrumbCategory = _name;
        }
    }
}

现在,您应该可以用它来装饰控制器了.

Now you should be able to decorate your controller with it.

[BreadCrumb("MyCategory")]
class MyController:Controller
{
}

这篇关于在ASP.NET MVC Core控制器的构造函数中设置ViewBag属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆