How to set ViewBag properties for all Views without using a base class for Controllers?

后端 未结 8 2064
故里飘歌
故里飘歌 2020-11-28 01:21

In the past I\'ve stuck common properties, such as the current user, onto ViewData/ViewBag in a global fashion by having all Controllers inherit from a common base controlle

相关标签:
8条回答
  • 2020-11-28 02:11

    The best way is using the ActionFilterAttribute. I'll show you how to use it in .Net Core and .Net Framework.

    .Net Core 2.1 & 3.1

    public class ViewBagActionFilter : ActionFilterAttribute
    {
        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);
        }
    }
    

    Then you need to register this in your startup.cs.

    .Net Core 3.1

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

    .Net Core 2.1

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

    Then you can use it in all views and pages

    @ViewData["Avatar"]
    @ViewBag.Avatar
    

    .Net Framework (ASP.NET MVC .Net Framework)

    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;
            }
        }
    
    }
    

    register your custom class in the global. asax (Application_Start)

    protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
    
            GlobalFilters.Filters.Add(new UserProfilePictureActionFilter(), 0);
    
        }
    

    Then you can use it in all views

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

    Also there is another way

    Creating an extension method on HtmlHelper

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

    Then you can use it in all views

    @Html.MyTest()
    
    0 讨论(0)
  • 2020-11-28 02:13

    Since ViewBag properties are, by definition, tied to the view presentation and any light view logic that may be necessary, I'd create a base WebViewPage and set the properties on page initialization. It's very similar to the concept of a base controller for repeated logic and common functionality, but for your views:

        public abstract class ApplicationViewPage<T> : WebViewPage<T>
        {
            protected override void InitializePage()
            {
                SetViewBagDefaultProperties();
                base.InitializePage();
            }
    
            private void SetViewBagDefaultProperties()
            {
                ViewBag.GlobalProperty = "MyValue";
            }
        }
    

    And then in \Views\Web.config, set the pageBaseType property:

    <system.web.webPages.razor>
        <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <pages pageBaseType="MyNamespace.ApplicationViewPage">
          <namespaces>
            <add namespace="System.Web.Mvc" />
            <add namespace="System.Web.Mvc.Ajax" />
            <add namespace="System.Web.Mvc.Html" />
            <add namespace="System.Web.Routing" />
          </namespaces>
        </pages>
      </system.web.webPages.razor>
    
    0 讨论(0)
提交回复
热议问题