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

后端 未结 8 2213
故里飘歌
故里飘歌 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()
    

提交回复
热议问题