Today we’ll take a break from discussing cutting edge framework enhancements and the latest and greatest. We’ll step back to take a look at the big picture. We will revisit some old questions of what is MVC, where do we start and how do we go about understanding the working of ASP.NET MVC.
If you are thorough with the basics, make sure you check our ASP.NET MVC Beginner to Advanced Tutorials
Thank you Sumit Maitra for co-authoring this article.
Revisiting MVC – the pattern
Trygve Reenskaug is attributed with the formulation of the Model View Controller pattern in 1979 while working at XEROX’ Palo Alto Research Center (PARC). You can refer to the original paper here, where it was originally referred to as Thing-Model-View-Controller. MVC was developed to solve the problem of users controlling large and complex data sets. The following rather unique image explains the main purpose of MVC – to bridge the gap between a User’s mental Model and the digital model that exists in the computer (original source).
Even in its early incarnation MVC easily achieved one thing clearly, that was to elegantly separate concerns. Even from the above diagram, we can easily make out the purpose of each component:
Model: Models represent data and thus knowledge. It could be a single object or a hierarchy/tree of objects. However, they should only be dealing with only one problem domain, for example data about appointments is not in the same problem domain as the color of rectangle used to represent the appointment on the screen.
View: Views are the visual representation of their respective Models. It can highlight certain Model attributes (properties) and suppress others.
Controllers: The unit of interaction that serves as a link between the User and the System. It presents data to User by arranging various Views appropriately. It also provides means for user input such as mouse operations and keystrokes. A controller should never supplement a View.
Evolution of the MVC Pattern
The above description of MVC pattern is almost 35 years old and as is obvious, it represented Software and Hardware architecture prevalent at the time; basically stateful applications, running on mainframes and accessed over remote terminals. These apps could hold on to application state for long periods. This is in contrast to current day architectures built on stateless protocols like HTTP the backbone of web applications.
Having said that, MVC has evolved really well and as ASP.NET MVC has shown, it can be very easily adapted. In context of Web Applications, MVC can be stated as follows:
Models: Classes that represent the problem domain (the problem/requirement we are trying to solve/accomplish). These classes also have code and logic to serialize and de-serialize the data into dedicated data stores as well as do validation and domain-specific logic. In ASP.NET MVC, this is the place for ORM or Data Access frameworks to do their magic.
Views: Views are essentially templates to generate the final HTML at runtime. Though, we say HTML, we could potentially return other types of Views like PDFs etc.
Controller: The class that manages the relationship between View and the Model. It is also responsible for accepting requests from the User and deciding which View to serve up if any.
The ASP.NET MVC Framework
The ASP.NET MVC Framework helps developers build applications that adhere to the MVC pattern. Additionally the MVC Framework started with the goal of enabling or providing themselves developer tools that enhance developer productivity and ease of use. Towards these goals, the framework has added functionality like HtmlHelpers, Validators that work unobtrusively, Attribute based Model validation, Pluggable components and dependency resolution (making it easier to use Dependency Injection, which in turn improved testability) and much more.
ASP.NET Web Forms and a bit of History
As we know, ASP.NET WebForms was with us from day one of ASP.NET. With the above insight into stateful systems and MVC, we can now see that WebForms was mimicking stateful systems over a stateless protocol (HTTP). This resulted in overheads like ViewState and Sessions that were not required for View Generation OR for the Model. With nothing enforcing separation of concerns, it was an easy system to abuse. Aided by tool support provided in Visual Studio, newbie developers migrating from VB6 and other stateful systems made full use of the ‘state’. Instead of working on separating concerns it was easy to couple the Controller logic and sometimes data logic in the code-behind. Needless to say, this resulted in brittle systems that had little or no extensibility and was difficult to understand and maintain. Soon it was apparent retrofitting state into a stateless system was a bad idea and something new was required. This is where the ASP.NET MVC found inspiration and was eventually released on March 13, 2009.
You can also read a very old article of mine that differentiates ASP.NET WebForms with ASP.NET MVC
Cross pollinating tooling support and framework features
ASP.NET MVC is currently in release 4 and working towards release 5 in September. It initially went very fast with bringing enhanced tooling support via Visual Studio Extensions and packages. However, now these tooling and framework enhancements have started flowing back into ASP.NET WebForms. For example, the Routing component that gave MVC its Rubyesq friendly URLs that didn’t end with a file name and also did not tie up URLs to physical paths, was initially ASP.NET MVC only, but soon it was released as a separate component and was available for use in both WebForms and ASP.NET MVC.Framework.
Thus WebForms continues to be a viable and supported way of building web applications, though it’s strongly suggest you adhere to MVC principles while designing such applications and keep the Code Behind usage to a bare minimum.
With the history of ASP.NET MVC covered, lets dive head-first into how things work!
ASP.NET MVC Pipeline
The above image is a high-level/happy path showing how ASP.NET MVC handles an incoming request from a user.
Step 1: The request goes through the ASP.NET stack and is handed over to the routing engine the first thing.
Step 2: Based on the route configuration, the routing engine looks for the appropriate controller. If the controller is found, it is invoked. If not found, a Controller not found is returned by the Routing engine.
Step 3: The Controller interacts with the Model as required. If there is incoming data, Model binding is done by ASP.NET MVC to make the incoming data into a strongly type Model if required.
Step 4: The model if invoked, retrieves or save appropriate data and returns to the controller.
Step 5: The controller then requests for a View with (or without) the data from Model. There may be one or more View engines registered so MVC Cycles through all the View engine until it finds one and renders the view. Then hands over the request to the ViewEngine which returns the Result to the Controller. The Controller send back the Result as a part of the HTTP response.
This is a highly simplified view of course. However the key steps remain the same.
The takeaway in this diagram is that ASP.NET MVC is dealing with straight HTTP, there is no ViewState munging or other fancy state management in the pipeline
A more detailed view is available in Steven Sanderson’s famous chart (from RedGate’s site).
Hooks into ASP.NET MVC
Earlier we had mentioned that the ASP.NET MVC had improved pluggability and dependency resolution support. A few examples of this is the support for Custom Controller Factory allowing IoC containers to inject dependencies into controllers. Also View Engines can be added or replaced completely. Additionally we have the Action Filter mechanism that allows custom handling of cross cutting concerns like Logging and Security.
With an idea of how MVC is working under the hood, let’s look at one more pattern that is prevalent now-a-days.
Derivative Patterns – Model View Presenter and Model View ViewModel
Following the generic MVC pattern for separation of concerns in Data Intensive, Interactive apps, a few derived patterns emerged at later points. We’ll look at two of them, the Model View Presenter and the Model View ViewModel pattern.
The Model View Presenter (MVVM)
The Model View Presenter pattern was first presented by Taligent in 1996. In this variation of MVC, the Presenter takes over the role of controller, as well as additional responsibility of interacting with the View and interpreting events on the View that are initiated by the user. It provides additional business logic that maps them on-to appropriate commands.
This results in the View in MVP getting more and more passive as compared to MVC.
The Model View ViewModel (MVVM)
The two main characteristics in this pattern are:
1. Model is split into Domain Model and View Model: The Domain Model represents how data is stored in the storage medium be it SQL or Document Databases. On the other hand, ViewModel represents the data to be viewed by the user. Normally data being viewed is a composition of one or more Domain model entities, along with other additional view related configurations.
2. Along with View Model, the MVVM pattern also proposes a data-binding mechanism that enables view to update itself on change of view models and vice-versa. When first proposed, this was supported with WPF and Siliverlight. Now-a-days framework like Knockout, Angular, Backbone etc. all support two way data binding.
That was a quick preview of what’s MVC with respect to ASP.NET MVC, its origins, history and usage in the .NET framework. We also took a refresher on the Model View Pattern and the Model View ViewModel patterns as well.