How to provide ASP.NET MVC2 master pages with a model indepdent of the controller
Asked Answered
A

2

3

I'm using strongly typed views and autofac for Dependency Injection under ASP.NET MVC2 and I'm trying to get a common dynamic header via dependency injection. I.e. i want this to happen without the view having to be away of this content even existing and i was hoping to avoid static discovery of the container and manual resolution, but I can't find a way to easily inject the master or a partial view included in the master via either ctor or property injection.

I can't imagine this is an uncommon task, but all I can find in terms of methods is Controller subclassing to stuff data into untyped ViewData, subclassing ViewModels to stuff master data into the model, or static resolution, all of which I'd prefer not to use. What am I overlooking?

EDIT: As has been pointed out DI into master pages is fighting the framework. So my question is badly framed: I don't really care about DI into master pages, but I have a dynamic element in the chrome of the site, i.e. the master page. Providing it with a model shouldn't be the responsibility of each controller using that master, as it is request context, not controller context specific. I fully admit that injection directly into master pages is inappropriate. If i could register a separate master controller to be invoked in addition, that would be even better. Is that possible? Given this task of providing the master with a model independent of the controller, what is the framework appropriate approach? Or does shared content in MVC require that each Controller has to know about that content?

Acinaciform answered 26/10, 2010 at 5:50 Comment(3)
See my answer below, but in summary, you are trying to use a hammer as a chisel. You are fighting the ASP.NET MVC framework and trying to make it more like webforms.Stoat
Yep, tried to solve the wrong end of the problem with wrong tool :(Acinaciform
Arne, I think it is a good question anyway - it is exactly what one searches for when trying to solve this problem. (And MVC3 supports this too, apparently ;))Eruct
S
7

You could use child actions.

Controller:

public class MyHeaderController: Controller
{
    private readony IRepository _repository;
    public MyHeaderController(IRepository repository)
    {
        _repository = repository;
    }

    [ChildActionOnly]
    public ActionResult Index() 
    {
        var model = _repository.GetSomeModel();
        return PartialView(model);
    }
}

And somewhere in your master page include it:

<div><%= Html.Action("Index", "MyHeader") %></div>
Suberin answered 26/10, 2010 at 6:31 Comment(3)
My problem with ChildActionOnly is that it puts the responsibility on each controller or forces me to use a controller base class. I want the ViewModel for the master to be Controller independent, since it's part of the chrome not of the controller behaviorAcinaciform
@Arne, I think you misunderstood the purpose of child actions. They have completely separate controller from the main controller rendering the view. The view model for the controller rendering the child action is completely independent from the view model used in the main controller rendering the view because they are two different controllers. And still you get DI into child action controllers at the same way you get for the main controllers.Suberin
Thanks for the clarification. Looks like I've misundestood ChildActionOnly. I thought that ChildActionOnly had to be defined in each controller. A separate controller is exactly what I want.Acinaciform
S
0

Your problems stem from confusing the term Dependency Injection, and fighting how the ASP.NET MVC framework works.

Also, you are using the term Dependency Injection in the wrong context. You are trying to use a hammer as a chisel.

MasterPages and views in ASP.NET MVC are intended to be used as templates. As stated in the other answer, child actions will solve your problem.

For future reference:

Dependency Injection refers to a means to configure what parameters to inject into class constructors, and have this done for you automatically, overriding some of the frameworks defaults. The purpose for this is to decouple components, so that they become more reusable, more testable, more unitary, amongst other good things.

DI refers to, and solves, a code issue, not a UI issue.

What you are trying to do is simply not possible. Ie, inject via constructors and properties a "dependency" into a masterpage. Again, MasterPages are intended by ASP.NET MVC to be used as just templates. They have no code behind class to instantiate via a constructor that would allow dependencies to be injected into it.

In other words, you are fighting the framework, which means you don't understand it.

If this sounds like nitpicking, I think this has to be highlighted as otherwise, you are confusing yourself and others who read this thread in the future.

Stoat answered 26/10, 2010 at 9:22 Comment(1)
But in fact, MVC master pages turn out to be code just like any other dynamic view in ASP.NET. Don't let what the framework currently supports get mistaken for best practice, it is pushing at the limitations of the framework that gets it improved :) ... Child actions are however a very nice solution here.Eruct

© 2022 - 2024 — McMap. All rights reserved.