Asp.net-Mvc

如何在不使用控制器基類的情況下為所有視圖設置 ViewBag 屬性?

  • March 27, 2011

過去,我通過讓所有控制器繼承自一個通用基礎控制器,以全域方式將通用屬性(例如目前使用者)粘貼到 ViewData/ViewBag 上。

這使我可以在基本控制器上使用 IoC,而不僅僅是針對此類數據進行全域共享。

我想知道是否有另一種將這種程式碼插入 MVC 管道的方法?

我沒有嘗試過,但您可能會考慮註冊您的視圖,然後在啟動過程中設置視圖數據。

因為視圖是即時註冊的,所以註冊語法並不能幫助您連接到Activated事件,因此您需要將其設置為Module

class SetViewBagItemsModule : Module
{
   protected override void AttachToComponentRegistration(
       IComponentRegistration registration,
       IComponentRegistry registry)
   {
       if (typeof(WebViewPage).IsAssignableFrom(registration.Activator.LimitType))
       {
           registration.Activated += (s, e) => {
               ((WebViewPage)e.Instance).ViewBag.Global = "global";
           };
       }
   }
}

這可能是我提出的那些“唯一的工具是錘子”式的建議之一;可能有更簡單的支持 MVC 的方法來實現它。

*編輯:*替代的,更少的程式碼方法 - 只需附加到控制器

public class SetViewBagItemsModule: Module
{
   protected override void AttachToComponentRegistration(IComponentRegistry cr,
                                                     IComponentRegistration reg)
   {
       Type limitType = reg.Activator.LimitType;
       if (typeof(Controller).IsAssignableFrom(limitType))
       {
           registration.Activated += (s, e) =>
           {
               dynamic viewBag = ((Controller)e.Instance).ViewBag;
               viewBag.Config = e.Context.Resolve<Config>();
               viewBag.Identity = e.Context.Resolve<IIdentity>();
           };
       }
   }
}

*編輯 2:*另一種直接從控制器註冊程式碼工作的方法:

builder.RegisterControllers(asm)
   .OnActivated(e => {
       dynamic viewBag = ((Controller)e.Instance).ViewBag;
       viewBag.Config = e.Context.Resolve<Config>();
       viewBag.Identity = e.Context.Resolve<IIdentity>();
   });

最好的方法是使用 ActionFilterAttribute。我將向您展示如何在 .Net Core 和 .Net Framework 中使用它。

.Net 核心 2.1 和 3.1

public class ViewBagActionFilter : ActionFilterAttribute
{

   public ViewBagActionFilter(IOptions<Settings> settings){
       //DI will inject what you need here
   }

   public override void OnResultExecuting(ResultExecutingContext context)
   {
       // for razor pages
       if (context.Controller is PageModel)
       {
           var controller = context.Controller as PageModel;
           controller.ViewData.Add("Avatar", $"~/avatar/empty.png");
           // or
           controller.ViewBag.Avatar = $"~/avatar/empty.png";

           //also you have access to the httpcontext & route in controller.HttpContext & controller.RouteData
       }

       // for Razor Views
       if (context.Controller is Controller)
       {
           var controller = context.Controller as Controller;
           controller.ViewData.Add("Avatar", $"~/avatar/empty.png");
           // or
           controller.ViewBag.Avatar = $"~/avatar/empty.png";

           //also you have access to the httpcontext & route in controller.HttpContext & controller.RouteData
       }

       base.OnResultExecuting(context);
   }
}

然後你需要在你的 startup.cs 中註冊它。

.Net 核心 3.1

public void ConfigureServices(IServiceCollection services)
{
   services.AddControllersWithViews(options => { 
       options.Filters.Add<Components.ViewBagActionFilter>();
   });
}

.Net 核心 2.1

public void ConfigureServices(IServiceCollection services)
{
   services.AddMvc(options =>
       {
           options.Filters.Add<Configs.ViewBagActionFilter>();
       });
}

然後您可以在所有視圖和頁面中使用它

@ViewData["Avatar"]
@ViewBag.Avatar

.Net 框架(ASP.NET MVC .Net 框架)

public class UserProfilePictureActionFilter : ActionFilterAttribute
{

   public override void OnResultExecuting(ResultExecutingContext filterContext)
   {
       filterContext.Controller.ViewBag.IsAuthenticated = MembershipService.IsAuthenticated;
       filterContext.Controller.ViewBag.IsAdmin = MembershipService.IsAdmin;

       var userProfile = MembershipService.GetCurrentUserProfile();
       if (userProfile != null)
       {
           filterContext.Controller.ViewBag.Avatar = userProfile.Picture;
       }
   }

}

在全域註冊您的自定義類。asax (Application_Start)

protected void Application_Start()
   {
       AreaRegistration.RegisterAllAreas();

       GlobalFilters.Filters.Add(new UserProfilePictureActionFilter(), 0);

   }

然後你可以在所有視圖中使用它

@ViewBag.IsAdmin
@ViewBag.IsAuthenticated
@ViewBag.Avatar

還有另一種方式

在 HtmlHelper 上創建擴展方法

[Extension()]
public string MyTest(System.Web.Mvc.HtmlHelper htmlHelper)
{
   return "This is a test";
}

然後你可以在所有視圖中使用它

@Html.MyTest()

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