Asp.net-Mvc
如何在不使用控制器基類的情況下為所有視圖設置 ViewBag 屬性?
過去,我通過讓所有控制器繼承自一個通用基礎控制器,以全域方式將通用屬性(例如目前使用者)粘貼到 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()