Sunday, September 28, 2008
Posted on Sunday, September 28, 2008 8:17:02 PM (Mountain Daylight Time, UTC-06:00)  Comments [0] | 
Categories: Ajax | ASP.NET MVC | Unit Testing

I'm becoming more and more reliant on unit testing as a critical part of my development process, and so I'm really excited to get a chance to build some web applications (internal research sites) using the new ASP.NET MVC (model-view-controller) bits. It's not "officially" released, but it's in "Preview 5", there is a "go-live" license, and it means you can build saner web apps without all the ASP.NET Web Forms shinanigans. So lets jump in!

I'm going to be doing a number of posts related to ASP.NET MVC, and this will be the "anchor" post - I will likely be editing it over time to add in more pointers to good resources.

The Basics

I'll point you to the official www.ASP.net/mvc site to get all the gory details, but at a high-level the things I like about this style of development are pretty simple:

  1. absolute control over the HTML and javascript that's sent to the browser,
  2. REST concepts baked in,
  3. separation of the presentation from the data from the logic (separation of concerns),
  4. Framework is test-driven development friendly

In my post on the Model View patterns, I gave some background on the idea of "MVC", so I'll consider that to be covered.

Getting Started

First thing to do is grab the bits. The installer and the source code (yes, Microsoft is publishing the source code for ASP.NET MVC!) are available at codeplex.com. This builds on .NET 3.5 and you will want to use Visual Studio 2008 (I don't think it's 100% required, but it makes the experience smoother).

Once installed, you get a new project type - ASP.NET MVC Application

mvc-project

Immediately after this dialog you are prompted to create a test project with your testing framework of choice. I like MBUnit, so that's what I selected.

mvc-project-test

So - how's that for sweet and different? Defining your unit testing strategy UP FRONT, instead of as an after thought. Tasty.

The Code

At Preview 5, the template kicks out a starter website, that's ready to roll. It's designed to show users how to do some of the common things - membership, roles, login / logout etc.

Not surprisingly the code is laid out as Models, Views and Controllers, with folders for each. Requests are routed to Controllers which then apply logic to the Model, and then determine which View to render to the client.

sol-exp

This is nice in that it helps ensure consistency across MVC projects.

Looking at the default project a little closer, we see some naming conventions at work...

details

We see two controllers - AccountController and HomeController. Then, under Views, we see two folders - Account and Home. This is not a mistake - although not required, setting things up like this simplifies the code you need to write. In the View subfolders, we see aspx pages with names that look like they may be methods, and that's exactly the case. The HomeController has 2 methods, which relate to the 2 View aspx files in /Views/Home. Initially this looks all jumbled in terms of the Url hiearchy, but that's taken care of by routing.

Routing 101

Unlike normal ASP.NET sites, the requested Url in an MVC site does not (usually) map to specific ASPX file on disk. In fact, you usually never see a file extension at all. For example, suppose you had a Url http://foo.com/orders - in traditional ASP.NET, a request to that url would look for a "default.aspx" file in the "orders" folder, and load that. With MVC, the Url is separated from the actual content on disk. Rather, decisions on what to execute are made based on what "routes" are setup for the site.

Essentially, routing is a way to map Urls to Controllers. In the sample site, a request to "/", actually routes to the HomeController, and specifically the Index action on the HomeController.

This is all setup in the Global.asax file, and looks like this:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
    );
}

The sample site is very simple, so the routing is very simple, but you can get much more creative with this stuff. What's really nice about this is that you can start to build RESTful applications - so getting the details of an order could be accessed via a url like /Orders/Details/123-098. You could also send along more information - either as another element in the url, or as a parameter, and specify the response format - much like how the ArcGIS Server 9.3 REST API works. This adds a tremendous amount of power and flexibility to the ASP.NET toolbox, allowing you to build one application which simultaneously provides a HTML based interface AND a Json interface - just by varying a parameter on the url (and a very minor amount of Controller code!)

Unit Testing

As noted earlier, unit testing is a key (but not mandatory) part of ASP.NET MVC. In the past, anyone concerned with testing usually kept their data classes (essentially the model) in a separate assembly which the web site referenced. This allowed the developer to write unit tests without meddling with classes in App_Code. But there was still all the code-behind logic which was a bear to test. This is where the Controllers come in. They do a lot of the logic that used to be in the code behinds. And they are testable. I'll be getting into this in more detail in upcoming posts, but you can test both the View output, as well as the routing logic.

Javascript: MSAjax, Dojo, jQuery oh my!

Since the developer has complete control over the markup that is emitted into the page, it's much easier to work with non-Microsoft Ajax libraries. This was somewhat complex in ASP.NET as the use of UserControls tended to cause all sorts of issues with respect to the ID of the HTML elements in the page. If you've ever looked at the HTML in a page and seen an id like "ctl1_ctl3_mydiv", that's ASP.NET trying to "help" you. This worked well for WebForms applications, but it's a total pain for Ajax apps where consistent ID's is critical. Why would we want to use another library? Consider that for sites using the ESRI Javascript API, the dojo toolkit is already loaded into the page, and it has all the Ajax plumbing we need to talk to back to the server - wouldn't it be nice to not load MSAjax if we did not have to? Later this week I'll be posting about some experiments I've been working on to see how this works.

 

Resources:

Tutorial Videos @ ASP.NET - good content for getting a handle on the main MVC ideas.

ASP.NET MVC Quick Start pages - high-level documentation for the framework

Comments are closed.