My thoughts on ASP.NET MVC
Late last year, I finally got over my preconceptions and gave ASP.NET MVC a try. The result has been a massive u-turn in my opinion of the framework. Now that I've used it in a couple of projects (including porting Worlds Apart to the framework), let me share a few of my thoughts with you.
Why I haven't tried ASP.NET MVC until now
I’ve spent a significant amount of time in the past few years adapting to .NET (1.1, then 2.0, then 3.5), and learning C#. Microsoft are fairly cranking out new .NET-related technologies, and staying anywhere near the cutting edge in all of them – while still meeting turnaround times in my day job, and without spending an unreasonable amount of time neglecting my girlfriend in favour of tech blogs – is very difficult indeed. I feel like I do at least as much learning as working, and so I’ve got to be a bit careful about which technologies I choose to pick up.
ASP.NET MVC didn’t make my initial cut because its primary selling points (testability, separation of concerns, more control over output markup) weren’t massive issues for me.
I’m dubious as to the value of unit-testing presentation-layer code – and the example tests in the ASP.NET MVC demo projects reinforced that opinion. AssertAreEqual(“A Magic String”, ViewData[“AMagicStringSetInTheController”]); is not a useful test. I’m down with rigorously unit-testing business- and service-layer code – but ASP.NET MVC neither assists nor enforces that. Emphasising testability of presentation-layer logic encourages programmers to put code in the presentation layer that doesn’t belong there – i.e. putting business logic in the controller, which in my opinion is just as bad as putting it in the code-behind. The vast majority of the code that I imagined would belong in my controller was “Grab data from service layer and pass it to the view”. Since the service-layer is typically making a database call, that’s an integration test by definition – and in any case, not very productive to unit-test since your service-layer presumably already has an extensive suite of tests.
Similarly, the separation of concerns aspect pushed by ASP.NET MVC enthusiasts didn’t appeal to me. If I had logic in my code-behind file that I didn’t feel belonged in my presentation-layer, I’d endeavour to push it down into the service layer. ASP.NET MVC doesn’t force you to keep business logic out of the controller – and that was more important to me than separating markup and presentation-layer logic.
I came to ASP.NET from LAMP rather than Winforms, and so having a greater degree of control over the output HTML did appeal to me, but not enough to justify the overhead of learning a new framework (not when there was other more important technology to learn – EF, WF, Silverlight). Besides, with a little bit of care and attention it was entirely possible to produce acceptable markup in “classic” ASP.NET. A few dozens of bytes of base 64 might offend a purist, but the programmer has a great deal more control over what goes into the ViewState than ASP.NET MVC enthusiasts seemed to admit.
Why I decided to try ASP.NET MVC
I decided to give ASP.NET MVC a try after I read Scott Gu’s blog post on the release candidate. There were a number of features that jumped out at me – model-to-UI validation messages were the first thing I noticed, and the scaffolding support in the Create View dialog was the tipping point. Taking the pain out of CRUD in just one project would save enough time to justify learning the framework. Scott Hanselman’s post on mixing and matching MVC and Webforms convinced me that this was a technology worth learning – since if it came to it, I could use the MVC RC’s scaffolding support to handle CRUD, and Webforms to handle everything else, and I’d still be saving time. Knowing how confusing it is to navigate documentation for a Microsoft RC (even now with the Beta out, most of the tutorials still refer to Preview 3, and so much has changed since then) I decided to get stuck in so I was prepared for when it hit.
The other factor was my increasing use of JQuery. I had made a few tentative forays into AJAX a few years ago before Javascript frameworks became all the rage, and subsequently I had worked fairly extensively with the ASP.NET AJAX framework. A friend of mine recommended JQuery to me last year, and (especially with Microsoft’s announcement that they’d be supporting it in VS) I loved it – but I was bothered by the inelegance of Webforms’ auto-generated control IDs. We needed lots of <%= ctrl.ClientID %> to make our scripts work – and that meant we couldn’t make our scripts entirely unobtrusive.
What I now like about ASP.NET MVC
The first indicator that ASP.NET MVC would be a technology I’d love was the pattern for strongly-typed views – especially strongly typed partial views. I had tried and failed a number of times to elegantly implement the following pattern in Webforms:-
<% foreach(Person p in myListOfPeople) {
html.RenderPartial(“PersonDetails”,p); } %>
- where myListOfPeople is some IEnumerable coming from my service layer, and “PersonDetails” is a site-wide person widget. The closest I could come to this in Webforms was using a Repeater, but that involved fairly complicated event plumbing in the code-behind (OnItemDataBound), and particularly inelegant use of the FindControl method.
The ModelBinder framework for retrieving data from a form post also appealed to me greatly – and I’m particularly happy that it’s getting even better (with business validation rules in the model being reflected in the binding, and errors being displayed to the user auto-magically).
What I still don't like about ASP.NET MVC
While I now see that ASP.NET MVC has a number of benefits for me, I still don’t like the way that a lot of references are passed around as strings – e.g. I’d really expect return View(“ViewName”) to throw a compiler warning if ViewName doesn’t exist. Similarly, a number of helper methods take a quite undiscoverable anonymous type to trigger a large set of options – and documentation for this is still a bit thin on the ground.
ASP.NET MVC uses quite a lot of reflection to do its stuff, and I think this has raised performance worries from some quarters. I’m quite convinced that bypassing __doPostBack is worth the overhead, but I think this is something that could be improved upon. Less reflection ought to mean even better performance, and since that’s always been something that people have had against ASP.NET it’d be nice to see it excelling now that it has an opportunity to.
Lastly, it’s still quite tricky to reconcile composite views with the MVC philosophy – particularly where there’s a widget on the MasterPage that needs its own ViewData (and so logically its own controller, since the core view’s controller really shouldn’t need to know about it). Html.RenderAction has – for now – sadly been relegated to the Futures DLL – since having a view spin up a new controller to render part of itself “violates” MVC (yet having the view run an action through the routing mechanism to produce a hyperlink, or any AJAX mojo, or even image tags – all similar forms of partial request – “don’t”). There are a couple of neat delegate-based solutions for having a controller spin up a friend to render part of a composite view, but nothing yet that we can elegantly drop onto a MasterPage.
Despite these drawbacks, I think it’s definitely a technology worth learning – particularly when the RC hits hopefully this month.
Post new comment