Search code examples
asp.netasp.net-mvclayoutviewmodel

.NET MVC - How to get Controller/View specific data to the Layout level from the Model without using ViewBag/ViewData


How do I access the View Model from inside a Layout? I can only think to use ViewBag and ViewData, which seems to contradict the MVC pattern.

I would like to do this because I don't like the way .NET MVC is designed when it comes to pushing data to layouts and non-layout views.

Once can pass a model to the "content root view" (i.e Return View(myModel)), but cannot do the same when it comes to the layout. For the layout, one is forced to use ViewBag or ViewData.

I like the idea of having a "data tree" that perfectly corresponds to my "view tree", and have each view pick its own values from the data, and pass-on the right node to its child views at the moment of including them. I like that because it avoids key name conflicts that you might encounter when using a single dictionary-like collection like ViewBag or ViewData for a tree of views unaware of one another.

But that fact that .NET MVC doesn't allow passing models to the layout is forcing the use of two différent methods to do the same thing, i.e using ViewBag or ViewData for the layout, and a "data tree" model for the "content root view", which doesn't seem right to me.

I would have liked to have a single entry point for pushing data to my views, and that would have been the layout itself, not the "content root view".

So based on that, my idea was to stop using layouts completely and, instead, have a root view that would be used as a layout, which would include a tree of partials views, meaning I would never call @RenderBody(), but rather call Html.Partial() instead.

However, this is moving away from how .NET MVC is supposed to be used, and I know by experience it can lead to problems when not using a technology how it's supposed to be. So here is my dilemma, I don't know if I should just code it how I want it to be coded and take the risk of encountering problems further down the road, or just use .NET MVC the way I'm supposed to and be stuck with this hybrid way of passing data to my views.


Solution

  • I would be interested to see a specific code example of the problem you're facing, for context, if you have one?

    Going on what you've said, you are right to be suspicious that you've been forced into using the ViewBag as it's not really something we should be using if we can help it. Obviously it's there and can be a good "get out of jail free card", but sticking to view models is certainly better.

    Have you considered defining and using sections in your layout/view? They essentially work like a named version of RenderBody.

    For example, in your Layout you might have:

    @RenderSection("SideBar", required: false)
    

    This can be accessed from your view, like this:

    @model your.namespace.viewmodel    
    
    ... some view cshtml ...
    
    @section SideBar {
        <h4>Related content for @Model.Name</h4>
        ...
    }
    

    Check out this overview of sections, it includes more in depth examples and also how to define default section content on the occasions you don't want to pass anything.