ASP.NET MVC Framework (Part 1)

Two weeks ago I blogged about a new MVC (Model View Controller) framework for ASP.NET that we are going to be supporting as an optional feature soon.  It provides a structured model that enforces a clear separation of concerns within applications, and makes it easier to unit test your code and support a TDD workflow.  It also helps provide more control over the URLs you publish in your applications, and can optionally provide more control over the HTML that is emitted from them.

Since then I've been answering a lot of questions from people eager to learn more about it.  Given the level of interest I thought it might make sense to put together a few blog posts that describe how to use it in more detail.  This first post is one of several I'll be doing in the weeks ahead.

A Simple E-Commerce Storefront Application

I'm going to use a simple e-commerce store application to help illustrate how the ASP.NET MVC Framework works.  For today's post I'll be implementing a product listing/browsing scenario in it.

Specifically, we are going to build a store-front that enables end-users to browse a list of product categories when they visit the /Products/Categories URL on the site:

When a user clicks on a product category hyperlink on the above page, they'll navigate to a product category listing URL - /Products/List/CategoryName -  that lists the active products within the specific category:

When a user clicks an individual product, they'll navigate to a product details URL - /Products/Detail/ProductID - that displays more details about the specific product they selected:

We'll build all of the above functionality using the new ASP.NET MVC Framework.  This will enable us to maintain a "clean separation of concerns" amongst the different components of the application, and enable us to more easily integrate unit testing and test driven development.

Creating A New ASP.NET MVC Application

The ASP.NET MVC Framework includes Visual Studio Project Templates that make it easy to create a new web application with it.  Simply select the File->New Project menu item and choose the "ASP.NET MVC Web Application" template to create a new web application using it.

By default when you create a new application using this option, Visual Studio will create a new solution for you and add two projects into it.  The first project is a web project where you'll implement your application.  The second is a testing project that you can use to write unit tests against it:

You can use any unit testing framework (including NUnit, MBUnit, MSTest, XUnit, and others) with the ASP.NET MVC Framework.  VS 2008 Professional now includes built-in testing project support for MSTest (previously in VS 2005 this required a Visual Studio Team System SKU), and our default ASP.NET MVC project template automatically creates one of these projects when you use VS 2008. 

We'll also be shipping project template downloads for NUnit, MBUnit and other unit test frameworks as well, so if you prefer to use those instead you'll also have an easy one click way to create your application and have a test project immediately ready to use with it.

Understanding the Folder Structure of a Project

The default directory structure of an ASP.NET MVC Application has 3 top-level directories:

  • /Controllers
  • /Models
  • /Views

As you can probably guess, we recommend putting your Controller classes underneath the /Controllers directory, your data model classes underneath your /Models directory, and your view templates underneath your /Views directory. 

While the ASP.NET MVC framework doesn't force you to always use this structure, the default project templates use this pattern and we recommend it as an easy way to structure your application.  Unless you have a good reason to use an alternative file layout, I'd recommend using this default pattern.

Mapping URLs to Controller Classes

In most web frameworks (ASP, PHP, JSP, ASP.NET WebForms, etc), incoming URLs typically map to template files stored on disk.  For example, a "/Products.aspx" or "/Products.php" URL typically has an underlying Products.aspx or Products.php template file on disk that handles processing it.  When a http request for a web application comes into the web server, the web framework runs code specified by the template file on disk, and this code then owns handling the processing of the request.  Often this code uses the HTML markup within the Products.aspx or Products.php file to help with generating the response sent back to the client.

MVC frameworks typically map URLs to server code in a different way.  Instead of mapping URLs to template files on disk, they instead map URLs directly to classes.  These classes are called "Controllers" and they own processing incoming requests, handling user input and interactions, and executing appropriate application and data logic based on them.  A Controller class will then typically call a separate "View" component that owns generating the actual HTML output for the request.

The ASP.NET MVC Framework includes a very powerful URL mapping engine that provides a lot of flexibility in how you map URLs to Controller classes.  You can use it to easily setup routing rules that ASP.NET will then use to evaluate incoming URLs and pick a Controller to execute.  You can also then have the routing engine automatically parse out variables that you define within the URL and have ASP.NET automatically pass these to your Controller as parameter arguments.  I'll be covering more advanced scenarios involving the URL routing engine in a future blog post in this series.

Default ASP.NET MVC URL Routing to Controller Classes

By default ASP.NET MVC projects have a preconfigured set of URL routing rules that enable you to easily get started on an application without needing to explicitly configure anything.  Instead you can start coding using a default set of name-based URL mapping conventions that are declared within the ASP.NET Application class of the Global.asax file created by the new ASP.NET MVC project template in Visual Studio. 

The default naming convention is to map the leading URL path of an incoming HTTP request (for example: /Products/) to a class whose name follows the pattern UrlPathController (for example: by default a URL leading with /Products/ would map to a class named ProductsController).

To build our e-commerce product browsing functionality, we'll add a new "ProductsController" class to our project (you can use the "Add New Item" menu in Visual Studio to easily create a Controller class from a template):

Our ProductsController class will derive from the System.Web.MVC.Controller base class.  Deriving from this base class isn't required - but it contains some useful helper methods and functionality that we'll want to take advantage of later:

Once we define this ProductsController class within our project, the ASP.NET MVC framework will by default use it to process all incoming application URLs that start under the "/Products/" URL namespace.  This means it will be automatically called to process the "/Products/Categories", "/Products/List/Beverages", and "/Products/Detail/3" URLs that we are going to want to enable within our store-front application.

In a future blog post we'll also add a ShoppingCartController (to enable end users to manage their shopping carts) and an AccountController (to enable end users to create new membership accounts on the site and login/logout of it).  Once we add these two new controller classes to our project, URLs that start with /ShoppingCart/ and /Account/ will automatically be routed to them for processing.

Note: The ASP.NET MVC framework does not require that you always use this naming convention pattern.  The only reason our application uses this by default is because there is a mapping rule that configures this that was automatically added to our ASP.NET Application Class when we created the new ASP.NET MVC Project using Visual Studio.  If you don't like this rule, or want to customize it to use a different URL mapping pattern, just go into the ASP.NET Application Class (in Global.asax) and change it. I'll cover how to-do this in a future blog post (when I'll also show some of the cool scenarios the URL routing engine enables).

Understanding Controller Action Methods

Now that we have a created a ProductsController class in our project we can start adding logic to handle the processing of incoming "/Products/" URLs to the application.

When defining our e-commerce storefront use cases at the beginning of this blog post, I said we were going to implement three scenarios on the site: 1) Browsing all of the Product Categories, 2) Listing Products within a specific Category, and 3) Showing Details about a Specific Product.  We are going to use the following SEO-friendly URLs to handle each of these scenarios:

URL Format Behavior URL Example
/Products/Categories Browse all Product Categories /Products/Categories
/Products/List/Category List Products within a Category /Products/List/Beverages
/Products/Detail/ProductID Show Details about a Specific Product /Products/Detail/34

There are a couple of ways we could write code within our ProductsController class to process these three types of incoming URLs.  One way would be to override the "Execute" method on the Controller base class and write our own manual if/else/switching logic to look at the incoming URL being requested and then execute the appropriate logic to process it.

A much easier approach, though, is to use a built-in feature of the MVC framework that enables us to define "action methods" on our controller, and then have the Controller base class automatically invoke the appropriate action method to execute based on the URL routing rules in use for our application.

For example, we could add the below three controller action methods to our ProductsController class to handle our three e-commerce URL scenarios above:

The URL routing rules that are configured by default when a new project is created treat the URL sub-path that follows the controller name as the action name of the request.  So if we receive a URL request of /Products/Categories, the routing rule will treat "Categories" as the name of the action, and the Categories() method will be invoked to process the request.  If we receive a URL request of /Products/Detail/5, the routing rule will treat "Detail" as the name of the action, and the Detail() method will be invoked to process the request, etc. 

Note: The ASP.NET MVC framework does not require that you always use this action naming convention pattern.   If you want to use a different URL mapping pattern, just go into the ASP.NET Application Class (in Global.asax) and change it.

Mapping URL Parameters to Controller Action Methods

There are several ways to access URL parameter values within the action methods of Controller classes.

The Controller base class exposes a set of Request and Response objects that can be used.  These objects have the exact same API structure as the HttpRequest/HttpResponse objects that you are already familiar with in ASP.NET.  The one important difference is that these objects are now interface based instead of sealed classes (specifically: the MVC framework ships with new System.Web.IHttpRequest and System.Web.IHttpResponse interfaces).  The benefit of having these be interfaces is that it is now easy to mock them - which enables easy unit testing of controller classes.  I'll cover this in more depth in a future blog post. 

Below is an example of how we could use the Request API to manually retrieve an ID querystring value from within our Detail action method in the ProductsController class:

The ASP.NET MVC framework also supports automatically mapping incoming URL parameter values as parameter arguments to action methods.  By default, if you have a parameter argument on your action method, the MVC framework will look at the incoming request data to see if there is a corresponding HTTP request value with the same name.  If there is, it will automatically pass it in as a parameter to your action method.

For example, we could re-write our Detail action method to take advantage of this support and make it cleaner like below:

In addition to mapping argument values from the querystring/form collection of a request, the ASP.NET MVC framework also allows you to use the MVC URL route mapping infrastructure to embed parameter values within the core URL itself (for example: instead of /Products/Detail?id=3 you could instead use /Products/Detail/3). 

The default route mapping rule declared when you create a new MVC project is one with the format: "/[controller]/[action]/[id]".  What this means is that if there is any URL sub-path after the controller and action names in the URL, it will by default be treated as a parameter named "id" - and which can be automatically passed into our controller action method as a method argument.

This means that we can now use our Detail method to also handle taking the ID argument from the URL path (e.g: /Products/Detail/3):

I can use a similar approach for the List action so that we can pass in the category name as part of the URL (for example: /Products/List/Beverages).  In the interest of making the code more readable, I made one tweak to the routing rules so that instead of having the argument name be called "id" it will be called "category" for this action.

Below is a version of our ProductsController class that now has full URL routing and parameter mapping support implemented:

Note above how the List action takes the category parameter as part of the URL, and then an optional page index parameter as a querystring (we'll be implementing server-side paging and using that value to indicate which page of category data to display with the request). 

Optional parameters in our MVC framework are handled using nullable type arguments on Controller Action methods.  Because the page parameter on our List action is a nullable int (that is what "int?" means syntactically), the MVC framework will either pass in a value if it is present in the URL - or pass in null if not.  Check out my previous post on the ?? null coalescing operator to learn a useful tip/trick on how to work with nullable types that are passed as arguments like this.

Building our Data Model Objects

We now have a ProductsController class and three action methods on it ready to process incoming web requests.  Our next step will be to build some classes that will help us work with our database to retrieve the appropriate data needed to handle these web requests.

In an MVC world "models" are the components of an application that are responsible for maintaining state.  With web applications this state is typically persisted inside a database (for example: we might have a Product object that is used to represent product data from the Products table inside our SQL database).

The ASP.NET MVC Framework enables you to use any data access pattern or framework you want in order to retrieve and manage your models.  If you want to use ADO.NET DataSets/DataReaders (or abstractions built on top of them) you can.  If you prefer to use an object relational mapper (ORM) like NHibernate, LLBLGen, WilsonORMapper, LINQ to SQL/LINQ to Entities you can absolutely use those as well.

For our e-commerce sample application I'm going to use the built-in LINQ to SQL ORM shipped in .NET 3.5 and VS 2008.  You can learn more about LINQ to SQL from my ongoing blog tutorial series that covers it (in particular make sure to check out my Part1, Part2, Part3 and Part4 posts). 

I'll start by right-clicking on the "Models" sub-directory of our MVC web project inside VS and choose the "Add New Item" option to add a LINQ to SQL model.  Within the LINQ to SQL ORM designer I'll define three data model classes that map to the Categories, Products, and Suppliers table inside the SQL Server Northwind sample database (read Part 2 of my LINQ to SQL series to learn how to-do this):

Once we've defined our LINQ to SQL data model classes, I'll then add a new NorthwindDataContext partial class to our Models directory as well:

Within this class I'll define a few helper methods that encapsulate some LINQ expressions that we can use to retrieve the unique Category objects from our database, retrieve all Product objects within a specific category in our database, as well as retrieve an individual Product object based on a supplied ProductID:

These helper methods will make it easy for us to cleanly retrieve the data model objects needed from our ProductsController class (without having to write the LINQ expressions within the Controller class itself):

We now have all of the data code/objects we need to finish implementing our ProductsController functionality. 

Finishing the Implementation of our ProductsController Class

Controllers in a MVC based application are responsible for processing incoming requests, handling user input and interactions, and executing appropriate application logic based on them (retrieving and updating model data stored in a database, etc).

Controllers typically do not generate the specific HTML response for a request.  The task of generating an HTML response is instead owned by "View" components within the application - which are implemented as separate classes/templates from Controllers.  Views are intended to be focused entirely on encapsulating presentation logic, and should not contain any application logic or database retrieval code (instead all app logic should be handled by the Controller).

In a typical MVC web workflow, Controller action methods will handle the incoming web request, use the incoming parameter values to execute appropriate application logic code, retrieve or update data model objects from a database, and then select a "View" to use to render an appropriate UI response back to a browser.  As part of picking the appropriate View to render, the Controller will explicitly pass in (as arguments) all of the data and variables required by the "View" in order to for it to render the appropriate response:

You might be wondering - what is the benefit of separating the Controller and the View like this?  Why not just put them in the same class?  The primary motivation in partitioning the application like this is to help enforce the separation of your application/data logic from your UI generation code.  This makes it much easier to unit test your application/data logic in isolation from your UI rendering logic.  It can also help make your application more maintainable over time - since it makes it harder for you to accidentally add application/data logic in your view templates.

When implementing the three controller action methods of our ProductsController class, we'll use the incoming URL parameter values to retrieve the appropriate model objects from our database, and then pick a "View" component to use to render an appropriate HTML response.  We'll use one of the RenderView() methods on the Controller base class to specify the View we want to use, as well as explicitly pass in the specific data that we want the View to use to render its response.

Below is the final result of our ProductsController implementation:

Notice that the number of lines of code in our action methods above is pretty small (two lines each).  This is partly because the URL parameter parsing logic is handled entirely for us by the MVC framework (saving us from having to write a lot of this code).  This is also partly because the product browsing scenario is fairly simple from a business logic perspective (the action methods are all read-only display scenarios). 

In general, though, you'll often find that you'll have what are sometimes called "skinny controllers" - meaning controller methods full of relatively terse action methods (less than 10 lines of code).  This is often a good sign that you have cleanly encapsulated your data logic and factored your controller logic well.

Unit Testing our ProductsController

You might be surprised that the next step we are going to work on is to test our application logic and functionality.  You might ask - how is that even possible?  We haven't implemented our Views, and our application currently doesn't render a single tag of HTML.  Well, part of what makes an MVC approach attractive is that we can unit test the Controller and Model logic of applications completely independently of the View/Html generation logic.  As you'll see below we can even unit test these before we create our Views.

To unit test the ProductsController class that we've been working on, we'll add a ProductsControllerTest class into the Test Project that was added to our solution by default when we created our ASP.NET MVC Application using Visual Studio:

We'll then define a simple unit test that tests the Detail action of our ProductsController:

The ASP.NET MVC framework has been designed specifically to enable easy unit testing.  All core APIs and contracts within the framework are interfaces, and extensibility points are provided to enable easy injection and customization of objects (including the ability to use IOC containers like Windsor, StructureMap, Spring.NET, and ObjectBuilder).  Developers will be able to use built-in mock classes, or use any .NET type-mocking framework to simulate their own test versions of MVC related objects.

In the unit test above, you can see an example of how we are injecting a dummy "ViewFactory" implementation on our ProductsController class before calling the Detail() action method.  By doing this we are overriding the default ViewFactory that would otherwise handle creating and rendering our View.  We can use this test ViewFactory implementation to isolate the testing of just our ProductController's Detail action behavior (and not have to invoke the actual View to-do this).  Notice how we can then use the three Assert statements after the Detail() action method is called to verify that the correct behavior occurred within it (specifically that the action retrieved the correct Product object and then passed it to the appropriate View).

Because we can mock and simulate any object in the MVC framework (including IHttpRequest and IHttpResponse objects), you do not have to run unit tests in the context of an actual web-server.  Instead, we can create our ProductsController within a normal class library and test it directly.  This can significantly speed up the execution of unit tests, as well as simplify the configuration and running of them.

If we use the Visual Studio 2008 IDE, we can also easily track the success/failure of our test runs (this functionality is now built-into VS 2008 Professional):

I think you'll find that the ASP.NET MVC Framework makes writing tests easy, and enables a nice TDD workflow.

Rendering UI with Views

We've finished implementing and testing the application + data logic for the product browsing section of our e-commerce application.  Now we need to implement the HTML UI for it. 

We'll do this by implementing "Views" that render the appropriate UI using the view-related data objects that our ProductsController action method provided when calling the RenderView() method:

In the code example above the RenderView method's "Categories" parameter is indicating the name of the view we want to render, and the second parameter is a list of category objects that we want to pass to the view and have it use as data to generate the appropriate HTML UI for.

The ASP.NET MVC Framework supports the ability to use any templating engine to help with generating UI (including existing templating engines like NVelocity, Brail - as well as new ones you write yourself).  By default the ASP.NET MVC Framework uses the existing ASP.NET Page (.aspx), Master Page (.master), and UserControl (.ascx) support already within ASP.NET. 

We'll be using the built-in ASP.NET view engine to implement our E-commerce Application UI.

Defining a Site.Master File

Because we are going to be building many pages for our site, we'll start our UI work by first defining a master page that we can use to encapsulate the common HTML layout/chrome across the site. We'll do this in a file called "Site.Master" that we'll create under the \Views\Shared directory of our project:

We can reference an external CSS stylesheet to encapsulate all styles for the site, and then use the master page to define the overall layout of the site, as well as identify content placeholder regions where we'll want pages to be able to fill in page specific content.  We can optionally use all of the cool new VS 2008 designer features when doing this (including the HTML split-view designer, CSS Authoring, and Nested Master Pages support).

Understanding the /Views Directory Structure

By default when you create a new ASP.NET MVC Project using Visual Studio, it will create a "Shared" sub-directory underneath the "Views" directory root.  This is the recommended place to store Master Pages, User Controls, and Views that we want to share across multiple Controllers within the application.

When building views that are specific to an individual controller, the default ASP.NET MVC convention is to store them in sub-directories under the \Views root.  By default the name of a sub-directory should correspond to the Controller name.  For example, because the Controller class we have been building is called "ProductsController", we will by default store the Views specific to it within the \Views\Products sub-directory:

When we call the RenderView(string viewName) method within a specific Controller, the MVC framework will automatically first look for a corresponding .aspx or .ascx view template underneath the \Views\ControllerName directory, and then if it can't find an appropriate view template there it will check the \Views\Shared directory for one:

Creating a Categories View

We can create the "Categories" View for our ProductsController within Visual Studio by using the "Add New Item" menu option on the Products directory and selecting the "MVC View Page" item template.  This will create a new .aspx page that we can optionally associate with our Site.Master master page to pick up the overall look and feel of the site (and just like with master pages you get full WYSIWYG designer support):

When building applications using an MVC pattern, you want to keep your View code as simple as possible, and make sure that the View code is purely about rendering UI.  Application and data retrieval logic should only be written inside Controller classes.  Controller classes can then choose to pass on the necessary data objects needed to render a view when they call their RenderView method.  For example, below in the Categories action method of our ProductsController class we are passing a List collection of Category objects to the Categories view:

MVC View Pages by default derive from the System.Web.Mvc.ViewPage base class, which provides a number of MVC specific helper methods and properties that we can use in constructing our UI.  One of these ViewPage properties is named "ViewData", and it provides access to the view-specific data objects that the Controller passed as arguments to the RenderView() method.

From within your View you can access the "ViewData" in either a late-bound or strongly-typed way.  If your View derives from ViewPage, the ViewData property will be typed as a late-bound dictionary.  If your View derives from the generics based ViewPage<T> - where T indicates the data object type of the ViewData the Controller is passing to the View - then the ViewData property will be strongly typed to match the same type that your Controller passed in.

For example, my Categories View code-behind class below is deriving from ViewPage<T> - where I am indicating that T is a List of Category objects:

This means that I get full type-safety, intellisense, and compile-time checking within my View code when working against the ProductsController.Categories() supplied List<Category> ViewData:

Rendering our Categories View:

If you remember from the screenshots at the very beginning of this post, we want to display a list of the product categories within our Categories view:

I can write this HTML UI generation code in one of two ways within my Categories View implementation: 1) Using Inline Code within the .aspx file, or 2) Using Server Controls within the .aspx file and Databinding from my Code Behind

Rendering Approach 1: Using Inline Code

ASP.NET Pages, User Controls and Master Pages today support <% %> and <%= %> syntax to embed rendering code within html markup.  We could use this technique within our Categories View to easily write a foreach loop that generates a bulleted HTML category list:

VS 2008 provides full code intellisense within the source editor for both VB and C#.  This means we'll get intellisense against our Category model objects passed to the View:

VS 2008 also provides full debugger support for inline code as well (allowing us to set breakpoints and dynamically inspect anything in the View with the debugger):

Rendering Approach 2: Using Server Side Controls

ASP.NET Pages, User Controls and Master Pages also support the ability to use declarative server controls to encapsulate HTML UI generation.  Instead of using inline code like above, we could use the new <asp:listview> control in .NET 3.5 to generate our bulleted list UI instead:

Notice above how the ListView control encapsulates both rendering a list of values, as well as handles the scenario where no items are in the list (the <EmptyDataTemplate> saves us from having to write an if/else statement in the markup).  We could then databind our list of category objects to the listview control using code-behind code like below:

Important: In a MVC world we only want to put rendering logic in our View's code-behind class (and not any application or data logic).  Notice above how the only logic we have is to assign the strongly typed ViewData collection of Category objects to the ListView control.   Our ProductsController Controller class is the one that actually retrieves the list of Categories from the database - not the View. 

This ListView server-control version of our View template will then generate the exact same HTML as our in-line code version.  Because we don't have a <form runat="server"> control on the page, no viewstate, ID values or other markup will be emitted.  Only pure CSS friendly HTML:

 

Html.ActionLink Method

One of the things you might have noticed in both the inline-code and the server-control versions of the View code snippets above are calls to an Html.ActionLink method:

The Html object is a helper property on the ViewPage base class, and the ActionLink method is a helper on it that makes it easy to dynamically generate HTML hyperlinks that link back to action methods on Controllers. If you look at the HTML output picture in the section above, you can see some example HTML output generated by this method:

<a href="http://weblogs.asp.net/Products/List/Beverages">Beverages</a>

The signature of the Html.ActionLink helper method I am using looks like this:

string ActionLink(string text, object values);

The first argument represents the inner content of the hyperlink to render (for example: <a>text goes here</a>).  The second argument is an anonymous object that represents a sequence of values to use to help generate the actual URL (you can think of this as a cleaner way to generate dictionaries).  I will go into more detail on how exactly this works in a future blog post that covers the URL routing engine.  The short summary, though, is that you can use the URL routing system both to process incoming URLs, as well as to generate URLs that you can emit in outgoing HTML.  If we have a routing rule like this:

/<controller>/<action>/<category>

And then write this code within a ProductController's Category View:

<%= Html.ActionLink("Click Me to See Beverages", new { action="List", category="Beverages" } %>

The ActionLink method will use the URL mapping rules of your application to swap in your parameters and generate this output:

<a href="http://weblogs.asp.net/Products/List/Beverages">Click Me to See Beverages</a>

This makes it easy within your application to generate URLs and AJAX callbacks to your Controllers.  It also means you can update your URL routing rules in one place and have the code throughout your application automatically pick up the changes for both incoming URL processing and outgoing URL generation.

Important Note: To help enforce testability, the MVC framework today does not support postback events directly to server controls within your Views.  Instead, ASP.NET MVC applications generate hyperlink and AJAX callbacks to Controller actions - and then use Views (and any server controls within them) solely to render output.  This helps ensure that your View logic stays minimal and solely focused on rendering, and that you can easily unit test your Controller classes and verify all Application and Data Logic behavior independent of your Views.  I'll blog more about this in the future.

Summary

This first blog post is a pretty long one, but hopefully helps provide a reasonably broad look at how all the different components of the new ASP.NET MVC Framework fit together, and how you can build a common real world scenario with it.  The first public preview of the ASP.NET MVC bits will be available in a few weeks, and you'll be able to use them to do all of the steps I outlined above.

While many of the concepts inherent to MVC (in particular the idea of separation of concerns) are probably new to a lot of people reading this, hopefully this blog post has also show how the ASP.NET MVC implementation we've been working on fits pretty cleanly into the existing ASP.NET, .NET, and Visual Studio feature-set.  You can use .ASPX, .ASCX and .MASTER files and ASP.NET AJAX to create your ASP.NET MVC Views.  Non-UI features in ASP.NET today like Forms Authentication, Windows Authentication, Membership, Roles, Url Authorization, Caching, Session State, Profiles, Health Monitoring, Configuration, Compilation, Localization, and HttpModules/HttpHandlers all fully support the MVC model.

If you don't like the MVC model or don't find it natural to your style of development, you definitely don't have to use it.  It is a totally optional offering - and does not replace the existing WebForms Page Controller model.  Both WebForms and MVC will be fully supported and enhanced going forward.  You can even build a single application and have parts of it written using WebForms and parts written using an MVC approach if you want.

If you do like what you've seen from the above MVC post (or are intrigued and want to learn more), keep an eye on my blog over the weeks ahead.  I'll be covering more MVC concepts and use them to build out our e-commerce application to show more features of it.

Hope this helps,

Scott

Published Tuesday, November 13, 2007 3:45 AM by ScottGu

Comments

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:13 AM by TimothyP

I'm looking forward to the upcoming articles!

Thank you :-)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:17 AM by Rocky Moore

How will Ajax and data entry enter into this model (as Ajax has taken a great hold on data entry nowadays)?  That is, those that require postbacks, not to mention all the third part libraries that currently use the postback methods.  Is there any way to use them under this model?

Thanks.  Saw you video a couple weeks ago abou MVC, was pretty good!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:20 AM by Peter St Angelo

Yet again -another awesome post.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:24 AM by Mohamed

Hi Scott,

This is amazing, would it be possible for you to demonstrate this part in a screencast or maybe next part?

Or something like create a blog in 15 minutes?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:26 AM by Doga Oztuzun

Hey G! It was what i was waiting to see ! I can't wait to mess up with it.

I use CastleProject and I didn't like using Ajax so I wonder how to use ASP.NET Ajax feauters ? I was trying to create a helper class to use ASP.NET ajax in castleProject. Will you do it like HtmlHelper ?

Thank you !

Regards.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:34 AM by Mohamed

Hello Scott,

Have you and the team any plans of including something like scaffolding? where by pointing at a database table clean basic code would be generated for listing,viewing,adding,editing,deleting etc.?

This would be a great kick start for beginners like me.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:44 AM by PieterD

Wow, now that is a posting! And this is only part 1? ;-)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:45 AM by John

Hi Scott,

Thanks for the post. Since it is early days for this project and SL 1.1 is still in Alpha, are there any plans to allow us to use this MVC model for SL applications?

Thanks,

John

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:48 AM by Dirk

Same here, I love the "Part 1" part of the title (although I'll also be looking for the words "release date" ;-))

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:49 AM by Dillorscroft

Really excited as to where this is heading for ASP.NET

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:49 AM by Michael A Jensen

Scott,

This is a fantastic addition to the ASP.NET arena. I am looking forward to the future blogs as well as implementing the MVC methodology in production ASP.NET apps once VS2008 is released.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:53 AM by Anthony

Hi Scott,

Thanks for your insightfull posts. I want to follow this demo on my own computer, but I wonder where I can this ASP.NET MVC project template.

keep up the good work,

Anthony

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:00 AM by Martin H. Normark

I like the level of abstraction and seperation, which is something I've always done in the past by having 3 projects inside Visual Studio. One for data access, one for business logic and a website project for UI.

What MVC provides for me, seems to be a cleaner way of calling corresponding methods inside of those layers, and taking care of all the URL rewriting, parameter 'loading' and so forth.

But the fact that I sometimes need to use the same business logic and data access from other apps that websites, makes me think that I would not benefit that much from the MVC. I would end up with a lot of skinny-methods, but on the other hand it would be easy to use the same website with another application logic without rewriting the aspx codebehind files.

Looking forward to play with it myself, and see how it all fits in...

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:00 AM by ajaxus

Wow! Scott, thanks for the long post.

Cant wait for more info on these MVC concepts.

Cheers

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:09 AM by Bill Pierce

Can I only pass one object to the View via RenderView or is there a mechanism to pass multiple objects/value types?  I'm guessing the convention is to lead me towards an 'interface per view' contract that specifies all data that will be made available?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:11 AM by daniel

Cool intro Scott. I cannot wait to get first-hand experience

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:15 AM by Daniel

Where or when can I download the CTP?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:16 AM by David Ing

Scott - This looks very promising indeed, and for the first time in a while, makes the Microsoft ASP.NET story much more appealing to lots of us. Good job in getting it back on the rails... <ducks>

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:24 AM by fathinker

It's great!

And I wonder if the source code of this sample application is available.

Thanks a lot.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:24 AM by Bruno

Awesome!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:25 AM by Matteo Casati

I love this guy!!!

Waiting for the next episode, thanks Scott

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:33 AM by Sergey

Awesome article! Thank you, Scott. I've kicked you :)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:34 AM by Long

So cool !!!! I have learned so much from your blog. Thank you so much and keep posting plz.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:36 AM by Stuart Ballard

This all looks really cool!

I have one question: What was the reasoning behind having Html.ActionLink as opposed to a more standard ASP.NET type approach of an <asp:ActionLink runat="server".../> control? Using methods that generate strings of HTML seems like a step back from the server control architecture that makes ASP.NET so cool in the first place.

Of course it would be trivial to write an ActionLink server control that calls Html.ActionLink in its Render method. Have you considered including something like this?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:38 AM by Jonathan

Hey Scott,

Great article, can't wait to try it out. On a seperate note, any hint on when VS2008 will rtm?

Jonathan

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:39 AM by Mohammed Hossam

It is really similar to web client software factory WCSF, however from my experience with WCSF it turns out to be more overhead, may be because of the workflow, I hope this one is better and really makes our life easier

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:47 AM by Neil Bostrom

Fantastic post! So excited about getting my hands on the framework!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:48 AM by Rob

While you are talking about mocking objects for TDD, would you consider including how to mock out any orm being used.  Thanks

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:48 AM by brandyr

Can´t wait until the bits come out. Thanks for this overview Scott.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:56 AM by Ben Hayat

Hi Scott;

I'm sure you guys have spent a lot of work into this technology and it will take a good amount of time for us to become good at. My question is, do you think this kind of technology will make it's way to the Silverlight platform, so we both can benefit from the invested time and energy?

Thanks!

..Ben

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:56 AM by Steve

Since it adds a testing project, does this require Team System?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 8:56 AM by Mike

Awesome, thanks for this post! I was really looking forward to some more information on this project. To me, besides LINQ, it's the one thing I'm looking forward to most.

I have some questions that I hope you can answer:

1. Only Web Application model will be supported, not Web Site?

2. Is it also possible to have this URL mapped: /Products/Beverages/3 instead of /Products/Beverages?page=3 or does it _need_ the parameter name?

Also, some ideas and general remarks:

1. I'd love to see more helper methods for use in the views, I like how Ruby on Rails has many shortcuts for creating forms and formfields etc.

2. Migrations! Not a part of MVC but from my experience with Ruby on Rails I would love to see support for this somewhere, anywhere! It would fit perfectly with the more agile way of developing that is possible with ASP.NET MVC.

Again, thanks for this post, I can't wait for the first release!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:01 AM by Andy

Feature request - please please include a comparable feature to the Castle MonoRail SmartDispatcherController that automatically binds to Post variables submitted by form elements such as <input type="text" name="product[0].id" /> and <input type="text" name="product[1].name" />. Or is this sort of functionality what you see the current frameworks providing on top of Microsoft MVC?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:03 AM by Mark Lennox

Brillian article - it makes it very simple to understand!

Well done for all the hard work on the MVC implementation - looks like it is paying off! I'm first in line to get a copy of VS2008 and end my love/hate relationship with PageControllers :)

Thanks Scott!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:08 AM by Timo

What about Web Parts, are they supported ? Is it possible to develop Web Parts by using MVC ?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:10 AM by garygwang

Hi Scott,

Where I can download source code for this post?

Thanks,

Gary

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:11 AM by Scott S.

Thanks Scott.  I'm really excited to see this coming to ASP.NET.

What would happen in your products detail example when the user changes the product id in the url to something that isn't an integer such as "/Products/Detail/ABC"?  Will an exception be thrown since the ProductsController.Detail method is expecting an int?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:13 AM by vkl

Is it possible to test drive view in isolation, i.e. render it without full ASP.NET pipeline? It's necessary thing when using TDD for web development.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:13 AM by Vijay Santhanam

Awesome! Can't wait for the CTP!

How do you put the List page parameter into the core URL like you did with the category string? I guess I'm asking where you can define more  comprehensive routing rules.

Can you map a nullable type to a url segment? like /Products/List/CatName/23 and can you leave it blank like this /Products/List/CatName/?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:17 AM by Catto

Hey Now Scott,

Great content.

Thanks for the info,

Catto

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:21 AM by Rachit

I have been waiting for this for a long time. This will change the way we do ASP.Neting currently and will force others (adopters of MVC) to learn Generics for sure. All goodies! :)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:25 AM by Mike Hadlow

I'm also very keen to get my hands on the CTP. Scott, you mention, using Inversion of Control containers with the MVC framework. I'd be very interested in seeing a blog post on this subject. Also, will there be a sample application (with tests and IoC) available alonside the CTP?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:27 AM by Daniel

Very cool!  One thing I'd like to see guidance on is developing MVC apps with multiple UIs.  You say here that it's best to put your models and controllers in the web app, but say we want a Winforms, WPF, Silverlight, and Web UI all doing similar things. Or a Mobile Web UI and Desktop Web UI... Would these still each need their own Models and Controllers, or does it make sense to have one library that they all share?  If so, how is that supported?  I'm still new to MVC, so if I'm missing something conceptually here, tell me!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:33 AM by findleyd

This is great stuff. I can't wait to get my hands on it.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:34 AM by Bryan Sampica

Excellent Article - I'm really looking forward to this technology.  There has always been a disconnect between true enterprise development standards, and the typical website "page" model.  This exposes control over the process, and the end users experience.  Wonderful stuff!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:37 AM by efdee

Thank you for what I suspect will be among the most interesting .NET technologies to have been released in the last 2 years.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:53 AM by MattF

Great Post!

How would you go about populating several data driven dropdown lists as well as loading the page content without putting data access logic in the view?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:54 AM by Dragan Panjkov

Excellent, as always, Scott!

I was almost sure that something is cooking, because of suspicious silent on your blog in last few days. I knew that you were at ASP.NET Connections, but again I expected something like this.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:57 AM by Jeremy Sullivan

I really appreciate this material.  Do you support the MVC pattern over the MVP pattern?  Or are there just better scenarios for using each?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:57 AM by iDaniel

Right time, right place :-).

Looking forward to model, view and control.

cheers, idaniel

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:57 AM by Josh Stodola

Now THIS is the post I have been waiting for. Very nicely written, keep up the great work Scott!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 9:58 AM by prakash

Great explanation. Thanks Scott

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:03 AM by David Mays

Thanks for this excellent writeup. You've done a good job of clarifying some important points about the new pattern. Anyone familiar with other popular MVC frameworks for .net can see the comparison quite cleanly here.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:05 AM by Tim Glenn

Great Post. Could I do this with the Front Controller pattern as well? (Without the mvc framework)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:05 AM by Max

This looks spectacular! Can you tell us when to expect a (beta) release? Can't wait to try it out myself! :-)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:06 AM by Roger Jennings

Scott,

Thanks for the very detailed tutorial and demo of the forthcoming MVC, especially for including the unit test details. Your post would make a super book chapter. I'll be interested to see how you mock LINQ to SQL's DataContext for testing (particularly shopping cart updates).

When can we expect a similar chapter with SubSonic as the DAL and scaffolding provider? (see oakleafblog.blogspot.com/.../subsonic-will-be-toolset-for-microsofts.html)

--rj

P.S. Posted at 3:45 AM? When do you sleep?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:09 AM by suhair

Naming a framework after a desugn pattern really drives the novices like me to panic and delays experimenting with it. Till now i was learning design patterns transparently using the .net framework. Is there any plan to change the asp.net mvc framework name to something tasty?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:14 AM by Alex Boesel

This writeup is masterful! Thanks for the monumental effort; it's extremely helpful!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:22 AM by Kapil

Great, I saw your earlier material about MVC but somehow could not find that when it is going to be available. Now it is clear that it is part of VS 2008

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:23 AM by gabriel

a very great article!

waiting to download the first CTP release :)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:23 AM by Kayj

This looks very promising. I will definitely try this out. Thanks!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:26 AM by gabriel

Thank you!!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:29 AM by Mathieu Paul Le Clerc

So the controller deals with the incomming request.  If I understand correclty, if I need to add a new "page" to my website I need to modify my controller and recompile the application?

Whould I end up with a single controller entry

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:30 AM by Matthew Vogt

Awesome.  Can't wait for the bits.  You talked about using an ASP.Net ListView control that is not inside a <form runat="server"> tag.  What if I want to use controls that must be inside such a tag?  

It doesn't look like this will work with the ASP.Net AJAX UpdatePanel control.  Will you be enhancing ASP.Net AJAX so that it integrates with the new MVC stuff?  I can see wanting to hit a url like /Products/Detail/3 and it return just the markup for the detail of that product (or maybe a JSON serialized Product object).  Will this be easy?

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:31 AM by Carlo Folini

Hi Scott,

using server side controls I see a problem on handling the control naming convention with MVC framework (actually also with 'normal' asp.net coding).

If I have this code

<asp:TextBox ID="txtMyMessage" runat="server" />

in the calling page, I have to handle a name like

ctl00$ContentPlaceHolder1$txtMyMessage

How is it handled this situation in MVC?

Sorry if you planned to speculate on this in the following posts ;P

Great post!

Ciao

Carlo

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:36 AM by John R. Lewis

Awesome! I con't wait to start playing with this. One thing I'd like to see in a future post is, how are user controls that need a controller going to work? (For example, a data driven hierarchical menu that might live in the left pane of a web site.)

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:36 AM by oVan

Very nice to see this, can't wait to get the bits also!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:36 AM by Justin

Thanks very much!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:36 AM by Sondre Bjellås

The ASP.NET MVC Framework is looking good, but I'm unsure how this will fit into custom MOSS 2007 development. Are you taking into consideration that we would like to use this framework for custom development ontop of MOSS? MOSS includes it's own URL rewriting/handling, I expect that to create problems for this new framework.

Are you considering support and implementation on MOSS - this is important for a lot of companies as more and more solutions are being development on that platform, and not from a scratch with an empty ASP.NET solution.

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:41 AM by MikeBosch

This looks really great and I can't wait to start using it.  I had a few questions / comments on parts of the design.

1.  Wouldn't it make more sense to separate the models and controllers into their own class libraries?

2.  Will all the MVC features be available in VS 2005?

3.  How come URL rewriting is managed in the Global.asax?  Can this be managed from within a IHttpModule?

4.  How about making the action to execute a property of the [ControllerAction] attribute so it doesn't depend on the method name?  For example, [ControllerAction(Action="Detail")]

Looks great!

# re: ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 10:45 AM