Almost 2 months ago the ASP.NET team released a preview of the ASP.NET 3.5 Extensions, which is a set of new features added on top of ASP.NET 3.5 and ADO 2008: among all the goodies, the Extensions package includes the much awaited ASP.NET MVC.
In this series of articles we will see what this framework is about, how to build a web application using that pattern, and then we will see how to extend it and use its advanced features.
In the first part we will introduce it and see how to create the first MVC based web application.
What is ASP.NET MVC
ASP.NET MVC is a framework that allows developers to apply the MVC pattern in the development of an ASP.NET application, thus allowing a better separation of concerns, which results in better reusability and easier testing.
MVC was one of the concepts originally found in SmallTalk. MVC and the web seem like a match made in heaven and allow for a simple way of building complex web applications.
To understand why this recently re-discovered way of building web application was developed, we need to have a look at the pitfalls of the standard model, which is the web-form approach.
First, it is event based: it can be good or bad depending on how you look at it. Good because it helps VB6 and WinForms developers to smoothly migrate their skills to the web application development. Bad because there are dozens of events that are raised during the page life-cycle, and it's not trivial to understand where to put your code. Also because the process logic is tightly coupled with the page life-cycle, it is difficult to test using automated tests.
It also uses server forms and ViewState: again, as with the event based model, it can be good since this hides to the developer all the problems related to maintaining the state of the page (values of textboxes, contents of dropdowns and so on), but can also be bad if you want to control exactly how the page is rendered, and you don't need to maintain all the state.
Furthermore, it uses server controls: good because they render the HTML for you; bad since they render it the way they want.
With the MVC framework you gain back the control of the order in which things happen during the page life-cycle, of the way state is persisted between requests, and the code with which HTML is rendered. And thanks to a better separation of concerns it's easier to test the process logic. But all this control has a cost: you have to do everything by yourself.
So, while reading this and the following parts that will be published in the next weeks, keep in mind this: the MVC framework is not a replacement for the web-form programming model, but it's an alternative programming model, for those who want to have a better control and want to be able to also test the presentation logic.
The MVC Pattern
A lot has been said on the MVC pattern, so I'll just make a quick review and point you to other texts about this topic in the reference section.
The pattern MVC, which stands for Model-View-Controller, separates an application in three components: Model, View and Controller:
- Model: this is where all the business logic of the application resides: it can range from a simple static class that returns a dataset to a complex multi-assembly Business Logic Layer that uses an assembly specific to the Data Access Layer.
- View: at the other end of the application is the View, which displays the application's user interface and contains the representation of the data that have been retrieved by the Model. This doesn't have logic, other than the one strictly related to the presentation of data.
- Controller: between the two components stands the Controller. It acts as the orchestrator of all the interactions among the other components and the users: it handles the requests, reads the form values, passes them to the Model, decides which View to render and finally sends the data to be rendered to the View.
In this specific implementation of the MVC pattern the Passive View flavor is used: the View is not responsible of updating itself but everything is performed by the Controller. The following diagrams depicts the high-level flow of the page request in the ASP.NET MVC framework:
Figure 1: MVC Pattern Diagram
- The request comes from the client and hits the Controller.
- The Controller calls the Model in order to perform some "business" operations.
- The Model returns the results of the operations back to the Controller.
- The Controller decides which View needs to be rendered and sends it the data that must be rendered.
- Finally the View renders the output and sends the response back to the client.
But after all that talking let's see how to create a "Hello World" MVC web application.
Creating an ASP.NET MVC application
To build an ASP.NET MVC application you need to install:
- Visual Studio 2008 (you can also use Visual WebDeveloper Express, here is how)
- ASP.NET 3.5 Extensions
Open up your VS2008, File > New > Project. There are two project templates available after you install the extensions:
- ASP.NET MVC Web Application: creates a sample web application
- ASP.NET MVC Web Application and Test: creates a sample web application and testing project to the test the sample controllers
For this example select "ASP.NET MVC Web Application":
Figure 2: New Project window in Visual Studio 2008
This creates a project that is pre-populated with all the basic components of the MVC application:
Figure 3: Auto-populated ASP.NET MVC Project
- Content: this folder is meant to include all the styles and images for the UI of the web application.
- Controllers: this folder will contain all the classes for the controllers.
- Models: the classes for the model will be located in this folder. In a simple ASP.NET application they could be a DataSet, a LINQ model or, in a more complex application, this could contain a wrapper to the Business Logic which could live in a separate assembly.
- Views: separated in one folder per controller, here are all the Views (the aspx pages) that will be rendered back to the user.
- Views\Shared: this last "standard" folder contains anything that pertains to the Views, but not specific to just one View (for example, Master Pages, shared controls and so on).
As we saw, all the views, the aspx pages, are located in a sub-folder, with the following relative path:
/Views/Home/Index.aspx. Does this mean that a user that wants to go the home of my application must type in the browser's address bar the URL: http://www.example.com/Views/Home/Index.aspx?
The answer is no: as I said a few paragraphs above, during a typical request life-cycle, the Controller is the first element being hit, and the decision of which View to render is one of the last steps of the process. This is possible because ASP.NET MVC uses a URL Routing module which allows the URL used to access a given functionality to be disconnected from the physical location of the file that contains it, be it an ASPX View or the Controller class.
This way, instead of having http://www.example.com/ProjectReport.aspx?projId=56, the URL will be http://www.example.com/Projects/Report/56. This is better, both from a SEO (Search Engine Optimization) and usability standpoint.
Previously, when I said that the Controller was the first thing being hit, I was lying. The first component hit is the URL Routing Module: it gets the URL of the request, checks it against its list of routes and then, applying the rules of the specified
RouteHandler, calls the right Controller.
Let's see an example of how this works by looking at the default routes that are added by the ASP.NET MVC Project Template to the
Application_Start method of the global.asax.cs file.
The code above instructs the Routing module to accept any URL made by 3 parts and instantiate the Controller whose name is the "folder name" in the first part of the URL, call the Action specified in the second part and use the 3rd as parameter.
For example, if a browser makes a request to the URL "Project/Report/1", the MVC framework loads the
ProjectController, and inside this controller it calls the action method named
1 as value for the parameter named
Now that we setup the route table let's see how to write a Controller in order to be used by the MVC framework.
The anatomy of a Controller is pretty straightforward: a Controller is simply a class that inherits from
System.Web.Mvc.Controller. The class then contains some public methods, the Actions, that are marked with the attribute
[ControllerAction]. These are the methods that are specified in the action part of the URL. Each Action calls the model and then, once it has performed all the operations required, calls the RenderView method that sends back to the user the HTML of the View whose name is specified as parameter.
A View is a "normal" aspx file that, instead of inheriting from
System.Web.UI.Page, inherits from
System.Web.Mvc.ViewPage. That's the only requirement for an aspx page to be interpreted as a View.
Then, in a "really passive" implementation, the View should only display the data retrieved by the Controller, with the exception of perhaps some conditional logic for certain data. A passive view should not generate new data or transform it into different data structures.
In this first part of the series we saw an introduction to the Model-View-Controller framework built on top of ASP.NET. For sake of brevity and simplicity, I omitted some details or more advanced scenarios like how to customize the Routing engine, the Controller and the View Engine, but I'll briefly cover them in a future series on the advanced topics.
In the next part we will talk about one of the most important aspects of this framework: testability.
My name is Simone Chiaretta and I'm a software developer/architect coding on the .NET platform both for business and for fun since 2001, when .NET was still in Beta version.
I'm working as Senior Solution Developer for Avanade, an international consulting company jointly owned b...
This author has published 2 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.