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?
This list of possible methods with theirs pros and cons helped me a lot. Thanks for a great article!
Thanks a lot! Glad to help.
Thanks for the article. But I have a question. How is the value happening?
this.ViewBag.MyProperty = “value”;
I don’t understand your question. If you want to know how you can use that value in your View, it’s just as simple as typing
@ViewBag.MyProperty
(assuming it’s a string): otherwise, you have to cast it, such as@((YourClass)ViewBag.MyProperty).SomeProperty
instead.