When you're building a website featuring a whole lot of Views you most likely end up setting a lot of variables & properties in each and every ViewBag object: some common examples are stuff like IsAdmin, IsAuthenticated, AvatarURL and similar tropes. When such situation arises, in order to avoid to cut & paste the exact same bunch of code in each and every controller method, it's highly advisable to get the job done in a more convenient (i.e. centralized) way. The most widely-used approaches to fullfill this task are the following:
1. The Base Class.
1 2 3 4 5 6 7 8 |
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. It can also be opted-out at will (thanks to Frank V. E. for pointing it out in this StackOverflow thread).
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. The Module.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
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. The RegisterController hook.
1 2 3 4 5 |
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. The Global (.asax) ActionFilter.
1 2 3 4 5 6 7 |
public class MyPropertyActionFilter : ActionFilterAttribute { public override void OnResultExecuting(ResultExecutingContext filterContext) { filterContext.Controller.ViewBag.MyProperty = "value"; } } |
1 2 3 4 5 |
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.
Like (almost) always there isn't really a best choice here, it mostly depends on your project settings and your developer needs. That being said, my preference goes towards the latter for the aforementioned reasons.
And yours?