I’m new to MVC and I probably don’t completely understand its logic yet and that’s why I always get into troubles.
To my mind, MVC is supposed to separate three parts of a web-application: the Model (dealing with the data: fetching, changing etc.), the Controller (desciding what data to return as a response depending on a user request) and the View (transforming the data got from the Controller (eg. to HTML) for sending back to user as a response).
“Separation” means that those three elements are abstract from one another. The Controller doesn’t care about the details of the realization of the Model part (and vice versa), it just tells what data he needs to get (or to change) and knows how to process it, the Model has nothing to do with the View (that is with the way data would be transformed).
Finally, the Controller has nothing to do with the View transformation, he just knows what data need to be transformed (depending on a request) and in what way (that is eg. selecting the correct template for the current data).
And the View part is abstract from the Controller, its job is to transform the specific array of input data in some preset way.
So now let’s say I’ve got a web-site. It has the index page (/), and some non-index pages (/vacancy/, /about/, /articles/bytag/fun/5/ etc.).
At the top of each page there is a logo. The problem is: I want the logo to be a hyperlink to the index page on every page of my site except the index page itself (because I don’t want my pages to contain hyperlinks to themselves).
So I want “<img src=’logo.png’>” on the index page and “<a href=”/”><img src=’logo.png’></a>” on other pages.
Of course, i don’t want to repeat myself and create several templates (header_index and header_nonindex) with the same logo image. So, what I need to do is to check if I’m on the index page in some place of my template (that is inside the View part) and depending on the result to add or not to add the link tag.
And here i face a logical problem. I can’t get the adress in the View (because logically this part has nothing to do with user request, it transforms data, recieved from the Controller).
So I need my Controller to send the specific data (eg. the page adress, or the boolean like “isIndex”) to the View. But the View can’t “require” data from the Controller, the View is just the way data is transformed. So if any specific variable is needed for the transformation itself, adding it to the Controller would make the View dependent on the specific Controller and the Controller – related to the specific View which would break the whole idea of abstraction and separation.
Thus there is no way to do what I need without breaking the MVC logic.
Which part of this do I get wrong?
A classic conundrum, but not particularly isolated to MVC. In OOP you want to increase cohesion within a class and reduce coupling between classes. MVC raises this same principle to an architectural level, each component is responsible for its activity but is separated from the actions of the other two. This is the ideal situation, but just as in OOP, the ideal doesn’t imply absolute separation. They do share some data – controllers access entity models, construct view models, and interpret input (typically as models in web-based MVC). Views consume view models and, on the web, are the source of the inputs. The model is perhaps the most isolated.
The reality is that separation is not an absolute, but a continuum. You have more or less separation compared to other architectural patterns. MVC tends to be on the “more” separation end of architectural patterns, but not all MVC implementations, or even instances of applications within those frameworks, are created equal in this regard. As the saying goes, “you can write Fortran in any language,” meaning that you can, if you choose, violate the design pattern to any extent you want, even to the extent of corrupting it into another pattern.
That’s not always a bad thing. You have to be pragmatic about it. The goal, after all, is not to achieve a pure architectural implementation. The goal is to accomplish the business of the application. In your case, you have some UI goals that require that the view have access to some of the details about which controller is rendering it. ASP.NET MVC exposes this through the ViewContext property which, in turn, exposes a reference to the Controller, the RouteData, and the HttpContext.
You could choose to use these to accomplish your business goals at the expense of some corruption of the architectural pattern, that is, the view is now handling some “input” and making some decisions based on those values directly. Alternatively, you could also choose to keep your separation more clear by increasing the complexity of your view models, either by deriving from a base model which contains some housekeeping properties or, in MVC, employing the ViewBag as an extension of each model for the same purposes. This increases the coupling to the Controller since it now needs to be aware that the View needs these housekeeping properties in order to render correctly. Again, it’s a continuum – you’re increasing coupling, not creating coupling where it didn’t exist.
I’ve given up the idea of creating pure MVC. Yes, I want to stay as close as possible to the MVC framework’s paradigms. It’s easier to work with the framework than against it. When I have a goal, however, that causes me to violate separation of concerns (after thorough examination to ensure that I really need to), I’m more interested in doing it in a sustainable and maintainable way, than jumping through architectural hoops to do something for which the framework is not suited or which is best done in a way that the framework doesn’t anticipate.