0

I have such controller system in my project:

BaseController : Controller
AnyController : Controller

Code in my base Controller:

 protected ViewResult View(string viewName, BaseViewModel model)
 {   
   model.PromoBannerContent = _service.GetPromoBannerContent();               
   return base.View(viewName, model);
 }

BaseViewModel - it's the layout model. And example of simple Action:

public virtual ActionResult UpdateAccount()
        {
            AccountViewModel account = _accountService.GetUser(Luxedecor.User.UserId).ToAccountViewModel();
            return View(MVC.Account.Views.UpdateAccount, new 
            UpdateAccountViewModel()
            {
               AccountJson = JsonConvert.SerializeObject(account),
               States = _accountService.GetStates(account.Country)
            });
            }

Where UpdateAccountViewModel : BaseViewModel.So my layout page is looking like that:

@model Luxedecor.ViewModel.BaseViewModel
@if (Model.PromoBannerContent != null)
{ 
...//Some html code
}

It's working fine, but I need to render the html promo banner not at all controller pages. I mean that I have for example AccountController: BaseController and I don't need this banner the AccountController Views. So I can create boolean property in my BaseViewModel and pass it from each Action in AccountController and other Contollers... But I wonder is exist more elegant solution for this issue? Could anyone experienced help me?

So, this is solution, what I've used for that:

 public class RenderPromoBanner : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            filterContext.Controller.ViewBag.EnableBanner = true;          
        }   
    }

And then I've just used one if statement on the layout.

Alex Gurskiy
  • 346
  • 1
  • 7
  • 20
  • 1
    You will need to pass a `boolean` property to the view, but to automate this, one options would be to use an `ActionFilterAttribute` (say) `[RenderBanner]` which you apply to the relevant controllers. Refer [this answer](http://stackoverflow.com/questions/24408441/how-to-set-values-to-viewbag-in-actionfilterattribute-asp-mvc-5) for an example of something you could adapt –  Feb 17 '16 at 08:10
  • Can I use attribute to the controller( not View)? – Alex Gurskiy Feb 17 '16 at 08:24
  • 1
    Yes, you can apply an attribute to a controller (gets applied to all methods) or just to individual methods within a controller. –  Feb 17 '16 at 08:26
  • Thanks for your time. I'll try and let you know if it helps! – Alex Gurskiy Feb 17 '16 at 08:28
  • Thanks, Stephen, working like a magic )) – Alex Gurskiy Feb 17 '16 at 08:43
  • 1
    Pleasure - you might want to add your own answer (or append to the accepted answer) with the code you tried for the benefit of others –  Feb 17 '16 at 08:47
  • Thanks! I'll do it during several hours. – Alex Gurskiy Feb 18 '16 at 11:52

1 Answers1

1

If you need to decide whether you need the banner or not on a per-Action basis (e.g. some actions in a controller need a banner whereas others in the same controller don't), the Action needs to communicate whether the banner is needed. Using a boolean is a viable option for this. Also, you could move the call to _service.GetPromoBanner into the Action and set the model property there if the banner is needed.

If all Actions in a controller need a banner or not, you could also create another subclass for the controllers that need a banner. This new subclass inherits from BaseController and contains the code to get the banner content. If a controller needs a banner, it derives from BannerController else from BaseController:

class BaseController : Controller
{
    protected virtual ViewResult View(string viewName, BaseViewModel model)
    {   
        return base.View(viewName, model);
    }    
}

class BannerController : BaseController
{
    protected virtual ViewResult View(string viewName, BaseViewModel model)
    {   
        model.PromoBannerContent = _service.GetPromoBannerContent();               
        return base.View(viewName, model);
    }    
}
Markus
  • 20,838
  • 4
  • 31
  • 55