[Claudio Figueiredo] ASP.NET MVC Experiences 2, Overview

Setting expectations clear

What I’m trying to achieve here is not a "how to use" ASP.NET MVC or a Tutorial. For those I really recommend Scott Hanselman’s videos which were my first source on the subject.

It’s a hands on experience, a spike if you will, with the most prominent features of the framework.
It’s a evaluation on how it works checking it advantages and disadvantages, from my point of view, and trying reducing some friction that I’m encountering on using MonoRail in my new project. Don’t get me wrong, I have nothing against MonoRail, it is still the most mature, featured MVC implementation on .Net world and I would not find any friction on it if not checking on .Net MVC features.

Evaluation procedure

The criterias that I’ll use in my evaluation will be, in the following order of importance:

  • Testability
  • SoC
  • Extensibility
  • Manageability

This analysis might not be linear, but these will be the focused points.

Overview

First time I heard about .Net MVC and checked out it’s features, it looked to me a badly built copy of MonoRail. But I soon realized some very nice differences. Not on the project itself, but the behaviour of P&P conducting it’s development. The way they positioned themselves eager to hear the community feedback led to great improvements over the three released iterations. That made me realize the fact that the similarities between them were not coincidental. Maybe the coincidences lie in the fact that they are both implementations of the same pattern, or more likely intentional (unless Filters and ActionFilters are both Design Patterns affiliated to MVC and I don’t know ).

Anyway, this is good because the transition between them is almost seamless, but that’s another topic.

Application Model

Almost everyone I talked about it, thinks that .Net MVC is sitting onto an Application Model of it’s own. But the fact is that it’s standing over the ASP.NET 2.0 Application model. Just as any other ASP.NET 2.0 application, it inherits from HttpApplication and has it’s events and life cycle. In fact, the new cool routing system is registered just in Application_Start as any global register.

This allows some interesting (and freaking) options as running both WebForm and MVC simultaneously.

Even though I didn’t expect a whole new web platform, I kinda hoped the separation would be a little more clear, not that this clouds the benefits that it provides. What really bother me is finding out that the standard ViewEngine, implemented by the ViewPage, inherits directly from our dear old friend System.Web.UI.Page. This open up even freakier possibilities. The fact that you can do the same funky thing that you do with a WebForm on a MVC View really scares the hell out of me.

First thing a tried when I find that out, was: add a Server form, an asp:button, an event handler and, Voilá: - Back to the same beach we’ve been swimming the past few years. I know that the fact the you could do something doesn’t mean you should or would do it, but it gave me shivers anyway.

This also showed me that you could add any WebControl you like on the Page, and work with it freely as you would on WebForms but in fact you wouldn’t like, more on that later.

Views

As said before, the default ViewEngine is basically a HttpHandler inheriting from the standard Page model. That said, one may conclude that anything you can do on a Page could be done on a ViewPage and most can actually be done. Here a some observations about this cross model that I checked:

  • The layout scheme, as expected is the same MasterPage mechanism used in WebForms.
  • Custom controls can be used the same way if you add a server form to the View.
  • Yes YOU HAVE VIEWSTATE, but only when adding a server form to the View, otherwise you get a nice clean html to work with.
  • You can use UserControls inside a ViewPage, but you’ll end up with the whole ViewState/ServerForm stack polluting to your code.
  • You’ve got tracing enabled just as a WebForm.

The above issues worried me a little. … mixed up model but spaghetti code?

Then again I remembered that’s it’s a Microsoft Product anyway. No rants here, just saying that Microsoft is not a charity and as such can’t avoid cathering for the main customers in their current business model. This is just something I (and you reader) should bear in mind while reading this.

The good thing here, is that the View layer was nicely built. Although they allow more than I would like, what is done here is done in a beautiful way. View testing has been somewhat neglected on implementing MVC applications, but here we get a stronger model which we can test and extend in a natural way.

Some key points on Views:

Convention over Configuration

The first thing I noticed, and one that made very happy is that ASP.Net MVC Views and setting approach follow strictly the CoC principle. It’s is such on MR and should not be changed, so common sense prevailed here for the good.

The rule here is putting your views on /Views/{controller}/{action} and nothing more needs to be done. It can be changed setting a new ViewLocator, which is a resolver for View’s paths.

Even though everything seems the same, one addition that I really liked is the Shared Views concept, which is so obvious that I’ll refrain from explaining.

The introduction of the concept of Typed Views.

Binding a View to a model seems very natural on MVC. And every view is bound to a model indirectly. The introduced change allows you to strongly-type your View’s Data to it’s own Model, thus making it more intuitive than generic views, that most of the time aren’t really generic. Let’s check how’s that works.

That’s the code for a view called List that’ll be rendered by the List Action of the Home Controller.

   1: namespace Stormwind.MVC.Template.Views.Home {
   2:     #region usings
   3:  
   4:     using System.Web.Mvc;
   5:  
   6:     #endregion
   7:  
   8:     public partial class List : Viewpage {
   9:     }
  10: }

And that’s the Template:

   1: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="List.aspx.cs"           Inherits="Stormwind.MVC.Template.Views.Home.List" %>
   2: <ul>
   3:     <%
   4:         foreach (var pair in (IList<string>)ViewData["listItem"]) {
   5:     %><li>
   6:         <%= pair %></li>
   7:     <% } 
   8:     %>
   9: </ul>

There’s two important points here:

  1. The first is ‘public partial class List : ViewUserControl‘, notice that the view inherits from a specific base class. Among other things, this base class contain a property call ViewData. ViewData is nothing more than a KeyValuePair collection that is used to interchange data between the controller and the View. It’s almost exactly the same as a MonoRail property bag.
  2. The second is ‘ var pair in (IList<string>)ViewData["listItem"]‘. Notice the cast here. As an untyped collection, ViewData items should be casted before used in a not so intuitive way. Worst of all making refactoring harder and the view error prone.

The concept of Typed Views, come to solve these issues. Check it out.

   1: public partial class ListTyped : ViewPage<List<string>> {
   2: }

Notice that the view now inherits ‘ViewUserControl<List<string>>‘ allowing us to:

   1: <ul>
   2:     <%
   3:         foreach (var pair in ViewData.Model) {
   4:     %><li>
   5:         <%= pair %></li>
   6:     <% } 
   7:     %>
   8: </ul>

The inherited View sets the Model allowing us working more naturally and refactoring friendly now.

The ability to easily create and change a ViewEngine.

Creating and changing View Engines in MonoRail is not too difficult, but changing them in runtime is a little painful and doing that through Windsor makes it feels makes it feel unnatural and definitely not the expected behaviour, or at least one that requires more configuration than expected.

Creating a new view engine is incredibly easy, since the IViewEngine contract only has one method to implement - The RenderView method.

Of course, this post does not sums everything that the MVC Framework has to offer, but believe me, there’s not much more either. You’ll see soon in another post.

Well, Views are not that different from MonoRail or other MVC implementations, and given you have the ability to implement your own, it’s a very flexible structure.

Next post: Controllers.

Stay tuned.