Asp.net

在 ASP.NET MVC Core 控制器的建構子中設置 ViewBag 屬性

  • May 22, 2020

我的主題有某種麵包屑。控制器始終是類別。為了避免重複自己,我想在控制器的建構子中為所有這樣的操作設置它:

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

當我ViewBag.BreadcrumbCategory在佈局視圖中訪問時,它為空。在一個動作中它起作用:

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

我想知道在建構子中設置 ViewBag 屬性是不可能的?在執行此工作的每個操作上呼叫一個函式會很煩人,也不是一個好的做法。在另一個問題中,使用建構子是一個公認的答案,但正如我所說,這不起作用,至少對於 ASP.NET Core 而言。

有一個關於它的GitHub 問題,據說這是設計使然。您連結的答案是關於 ASP.NET MVC3,舊的遺留 ASP.NET 堆棧。

ASP.NET Core 是從頭開始編寫的,並使用不同的概念,專為可移植性(多平台)以及性能和現代實踐而設計,例如對依賴注入的內置支持。

最後一個使得無法ViewBag在建構子中設置,因為Constructor基類的某些屬性必須通過 Property Injection 注入,因為您可能已經註意到您不必在派生控制器中傳遞這些依賴項。

這意味著,當Controller呼叫 的建構子時HttpContextControllerContext不會設置 等的屬性。它們僅呼叫建構子並且存在對此對象的有效實例/引用後才設置。

正如 GitHub 問題中所指出的,它不會被修復,因為這是設計使然。

正如您在此處看到的,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)
   {
       base.OnActionExecuting(context);

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

現在你應該可以用它來裝飾你的控制器了。

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

引用自:https://stackoverflow.com/questions/40330391