2016-10-30 40 views
6

我的主题有某种面包屑。控制器始终是类别。为了避免重复自己,我想将它设置在控制器的构造像这样所有操作:在ASP.NET MVC核心控制器的构造函数中设置ViewBag属性

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

当我访问布局视图ViewBag.BreadcrumbCategory,其空。在行动它的作品:

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

我想知道在构造函数中设置ViewBag属性是不可能的?在做这项工作的每一个动作上都有一个函数需要调用会很麻烦,也没有好的做法。在another question使用构造函数是一个公认的answear,但正如我所说这不起作用,至少对于ASP.NET Core。

+3

您应该使用操作过滤器。 – SLaks

回答

9

有一个关于它的GitHub issue,它表明这是设计。您链接的答案是关于ASP.NET MVC3,旧的传统ASP.NET堆栈。

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

最后一个使得它不可能设置在构造ViewBag,因为Constructor基类的某些属性必须通过物业注射注射,因为你可能已经注意到了,你不必在你的派生控制器通过这些依赖。

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

正如GitHub问题所指出的那样,它不会被修复,因为这是通过设计。

正如你可以看到here,ViewBag依赖ViewDataViewData是在控制器初始化后填充。如果调用ViewBag.Something = "something",那么它将创建一个DynamicViewData类的新实例,它将在构造函数初始化后由一个实例替换。

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

以下示例假定您总是从Controller基类中派生出您的控制器。现在

public class BreadCrumbAttribute : IActionFilter 
{ 
    private readonly string _name; 

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

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

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

你应该能够用它来装饰您的控制器。

[BreadCrumb("MyCategory")] 
class MyController:Controller 
{ 
} 
相关问题