Monolithcode
Monolithcode

Reputation: 618

Pass ViewData to all actions without having to write it every time

All, I am simply trying to read a custom value from a loaded .config file into an MVC project.

So I set a value such as the below in my added .config file:

"AppSettings": {
    "Title": "Mobile Site"
  }

I've made a base controller to set the values

public abstract class ControllerBase : Controller
{
    protected Models.AppSettings _appSettings;
    private IConfiguration _config;
    public ControllerBase(IConfiguration config)
    {
        _config = config;
        _appSettings = new Models.AppSettings();
        _appSettings.SiteTitle = _config.GetSection("AppSettings").GetSection("Title").Value;

        ViewBag.Settings = _appSettings;
    }
}

This I can also confirm is working. The values are pulled through if I simply set the viewbag data in one of my actions.

public class AppController : ControllerBase
{
    public AppController(IConfiguration config) : base(config)
    {

    }
    // GET: /<controller>/
    public IActionResult Index()
    {
        ViewData["Settings"] = _appSettings;
        return View("Index");
    }

I can access the values in the view this way, but as the values I'm currenlty adding are simply what the site title is (so I can config these things in a simple .config file) I want stuff like the site title to be passed to every action without having to specifically pass it each and every time for every single action.

I tried following a video showing this working by settings this in the view:

@{
    ViewData["Logo"] = "~/img/bird.png";
    ViewData["Icon"] = "~/img/logo.ico";
    var Settings = ((Mobile.Models.AppSettings)ViewBag.Settings);
}

But the page will fail to load properly if again, I dont specify the settings within the action loading the page.

How can this be done? Can this be done any more?

Upvotes: 7

Views: 3176

Answers (1)

Ilya Chumakov
Ilya Chumakov

Reputation: 25029

MVC Core approach to implementing aspect-oriented functionality is the same as in MVC 5. There are at least two ways to inject a code before/after each action:

А. Override OnActionExecuting in your ControllerBase:

public override void OnActionExecuting(ActionExecutingContext context)
{
    ViewBag.foo = "1";
}

OR

B. Add ActionFilter to the controller (the filter has to be registered in DI):

public class TestFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        ViewBag.foo = "1";
        base.OnActionExecuting(context);
    }
}

[ServiceFilter(typeof(TestFilter))]
public class TestController : Controller
{
}

More examples: Asp.net Core 1.0 Action Filters. The second way is more flexible (for example, you can easily add the filter to a particular action).

Upvotes: 10

Related Questions