Access Viewbag property on all views

后端 未结 4 828
独厮守ぢ
独厮守ぢ 2021-02-14 02:22

How can I access some ViewBag properties across all my views? I want to have some information like current user name, etc accessible everywhere, but without having to to specifi

相关标签:
4条回答
  • 2021-02-14 02:52

    My current solution:

    Create a base controller with all needed properties (very useful and advisable).

    public abstract class BaseController : Controller {
        public string MyProperty { get; set; }
    }
    

    Inherits all your controllers, from the base controller.

    public class MyController : BaseController {
        //you can read your property here
    }
    

    In your views, add this line just after the "@model" sentence:

    @{ BaseController ctr = ViewContext.Controller as BaseController; }
    

    Now, you can use the property in your view, without populate the ViewBag, without the need of check and cast the ViewBag values, etc.

    In the view, you can use an simple inline expression:

    @(ctr.MyProperty)
    

    Or do some magic logic...

    @{
        if(ctr.MyProperty == "whatelse") {
            //do ...
        }
    }
    

    Easy, fast and comfortable.

    0 讨论(0)
  • 2021-02-14 02:53

    You can achieve what you want in a number of ways, each one with their pros and cons.

    1. With a Base Class

    public class BaseController : Controller
    {
        protected override ViewResult View(IView view, object model)
        {
            this.ViewBag.MyProperty = "value";
            return base.View(view, model);
        }
    }
    

    PROS: Quite simple to implement, few lines of code, highly reusable, can be opted-out at will (see comments below).

    CONS: Being forced to derive all your controllers from a base class might have some impact, especially if you have a lot of controllers already in place and/or you need to derive them from other base classes.

    2. With a Module

    public class ViewBagPropertyModule: 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.MyProperty= "value";
                };
            }
        }
    }
    

    PROS: None I’m aware of.

    CONS: None I’m aware of (except being a bit counterintuitive).

    3. With a RegisterController Hook

    builder.RegisterControllers(asm)
        .OnActivated(e => {
            dynamic viewBag = ((Controller)e.Instance).ViewBag;
            viewBag.MyProperty = "value";
        });
    

    PROS: Fast, secure, reusable: ideal for any IoC design pattern.

    CONS: Not always suited for small project and/or simple websites: if you’re not using IoC you’re often not using RegisterController at all.

    4. With an ActionFilter attribute

    public class MyPropertyActionFilter : ActionFilterAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            filterContext.Controller.ViewBag.MyProperty = "value";
        }
    }
    

    and then in your Global.asax.cs file:

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

    PROS: Easily the less-obtrusive method amongst those mentioned.

    CONS: None I’m aware of.

    I also wrote this article on my blog explaining all the above methods.

    0 讨论(0)
  • 2021-02-14 03:01

    The best and straight forward way to accomplish your requirement is to make a Custom Base Controller and inherit your Controller from this Base Controller.

    public class MyBaseController : Controller
    {
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            ViewBag.someThing = "someThing"; //Add whatever
            base.OnActionExecuting(filterContext);
        }
    }
    

    Now instead of inheriting Controller class,inherit MyBaseController in your Controller as shown :-

    public class MyOtherController : MyBaseController 
    {
        public ActionResult MyOtherAction()
        {
           //Your Stuff
           return View();
        }
        //Other ActionResults
    }
    
    0 讨论(0)
  • 2021-02-14 03:05

    One way: Create a custom attribute, then you can apply it globally in the FilterConfig. Then you don't have to do anything in your controllers.

    public class MyCustomViewActionFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            dynamic ViewBag = filterContext.Controller.ViewBag;
    
            ViewBag.Id = "123";
            ViewBag.Name = "Bob";
        }
    }
    

    In App_Start/FilterConfig.cs:

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new MyCustomViewActionFilter());
        }
    

    Another way if all you need is the User information. You can add the following to the top of your view:

    @using Microsoft.AspNet.Identity
    

    Then access your User Name using the following syntax:

    @User.Identity.GetUserName()
    

    You can also override the IPrincipal implementation and provide your own properties and methods to add more information you need to render.

    UPDATE: looking at MVC 6 in Asp.Net vNext this is actually baked into the framework. http://www.asp.net/vnext/overview/aspnet-vnext/vc#inj

    0 讨论(0)
提交回复
热议问题